mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-08 14:15:25 +08:00
NM-61: User group ACL fixes (#3546)
* feat(go): create default acl only for networks that are part of the group; * feat(go): update acls on user group update and delete; * feat(go): add migration for existing acls. * feat(go): check for network roles in migration.
This commit is contained in:
parent
996410fc61
commit
e4da84aa85
5 changed files with 186 additions and 6 deletions
|
@ -1263,6 +1263,19 @@ func ValidateCreateAclReq(req models.Acl) error {
|
|||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
for _, src := range req.Src {
|
||||
if src.ID == models.UserGroupAclID {
|
||||
userGroup, err := GetUserGroup(models.UserGroupID(src.Value))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, ok := userGroup.NetworkRoles[req.NetworkID]
|
||||
if !ok {
|
||||
return fmt.Errorf("user group %s does not have access to network %s", src.Value, req.NetworkID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ var CreateDefaultUserPolicies = func(netID models.NetworkID) {
|
|||
InsertAcl(defaultUserAcl)
|
||||
}
|
||||
}
|
||||
var ListUserGroups = func() ([]models.UserGroup, error) { return nil, nil }
|
||||
var GetUserGroupsInNetwork = func(netID models.NetworkID) (networkGrps map[models.UserGroupID]models.UserGroup) { return }
|
||||
var GetUserGroup = func(groupId models.UserGroupID) (userGrps models.UserGroup, err error) { return }
|
||||
var AddGlobalNetRolesToAdmins = func(u *models.User) {}
|
||||
|
|
|
@ -35,6 +35,7 @@ func Run() {
|
|||
updateHosts()
|
||||
updateNodes()
|
||||
updateAcls()
|
||||
updateNewAcls()
|
||||
logic.MigrateToGws()
|
||||
migrateToEgressV1()
|
||||
resync()
|
||||
|
@ -441,6 +442,48 @@ func updateAcls() {
|
|||
}
|
||||
}
|
||||
|
||||
func updateNewAcls() {
|
||||
if servercfg.IsPro {
|
||||
userGroups, _ := logic.ListUserGroups()
|
||||
userGroupMap := make(map[models.UserGroupID]models.UserGroup)
|
||||
for _, userGroup := range userGroups {
|
||||
userGroupMap[userGroup.ID] = userGroup
|
||||
}
|
||||
|
||||
acls := logic.ListAcls()
|
||||
for _, acl := range acls {
|
||||
aclSrc := make([]models.AclPolicyTag, 0)
|
||||
for _, src := range acl.Src {
|
||||
if src.ID == models.UserGroupAclID {
|
||||
userGroup, ok := userGroupMap[models.UserGroupID(src.Value)]
|
||||
if !ok {
|
||||
// if the group doesn't exist, don't add it to the acl's src.
|
||||
continue
|
||||
} else {
|
||||
_, ok := userGroup.NetworkRoles[acl.NetworkID]
|
||||
if !ok {
|
||||
// if the group doesn't have permissions for the acl's
|
||||
// network, don't add it to the acl's src.
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
aclSrc = append(aclSrc, src)
|
||||
}
|
||||
|
||||
if len(aclSrc) == 0 {
|
||||
// if there are no acl sources, delete the acl.
|
||||
_ = logic.DeleteAcl(acl)
|
||||
} else if len(aclSrc) != len(acl.Src) {
|
||||
// if some user groups were removed from the acl source,
|
||||
// update the acl.
|
||||
acl.Src = aclSrc
|
||||
_ = logic.UpsertAcl(acl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func MigrateEmqx() {
|
||||
|
||||
err := mq.SendPullSYN()
|
||||
|
|
|
@ -470,12 +470,14 @@ func createUserGroup(w http.ResponseWriter, r *http.Request) {
|
|||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
networks, err := logic.GetNetworks()
|
||||
if err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
for _, network := range networks {
|
||||
|
||||
for networkID := range userGroupReq.Group.NetworkRoles {
|
||||
network, err := logic.GetNetwork(networkID.String())
|
||||
if err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
acl := models.Acl{
|
||||
ID: uuid.New().String(),
|
||||
Name: fmt.Sprintf("%s group", userGroupReq.Group.Name),
|
||||
|
@ -599,6 +601,93 @@ func updateUserGroup(w http.ResponseWriter, r *http.Request) {
|
|||
},
|
||||
Origin: models.Dashboard,
|
||||
})
|
||||
|
||||
go func() {
|
||||
networksAdded := make([]models.NetworkID, 0)
|
||||
networksRemoved := make([]models.NetworkID, 0)
|
||||
|
||||
for networkID := range userGroup.NetworkRoles {
|
||||
if _, ok := currUserG.NetworkRoles[networkID]; !ok {
|
||||
networksAdded = append(networksAdded, networkID)
|
||||
}
|
||||
}
|
||||
|
||||
for networkID := range currUserG.NetworkRoles {
|
||||
if _, ok := userGroup.NetworkRoles[networkID]; !ok {
|
||||
networksRemoved = append(networksRemoved, networkID)
|
||||
}
|
||||
}
|
||||
|
||||
for _, networkID := range networksAdded {
|
||||
// ensure the network exists.
|
||||
network, err := logic.GetNetwork(networkID.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// insert acl if the network is added to the group.
|
||||
acl := models.Acl{
|
||||
ID: uuid.New().String(),
|
||||
Name: fmt.Sprintf("%s group", userGroup.Name),
|
||||
MetaData: "This Policy allows user group to communicate with all gateways",
|
||||
Default: false,
|
||||
ServiceType: models.Any,
|
||||
NetworkID: models.NetworkID(network.NetID),
|
||||
Proto: models.ALL,
|
||||
RuleType: models.UserPolicy,
|
||||
Src: []models.AclPolicyTag{
|
||||
{
|
||||
ID: models.UserGroupAclID,
|
||||
Value: userGroup.ID.String(),
|
||||
},
|
||||
},
|
||||
Dst: []models.AclPolicyTag{
|
||||
{
|
||||
ID: models.NodeTagID,
|
||||
Value: fmt.Sprintf("%s.%s", models.NetworkID(network.NetID), models.GwTagName),
|
||||
}},
|
||||
AllowedDirection: models.TrafficDirectionUni,
|
||||
Enabled: true,
|
||||
CreatedBy: "auto",
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
_ = logic.InsertAcl(acl)
|
||||
}
|
||||
|
||||
// since this group doesn't have a role for this network,
|
||||
// there is no point in having this group as src in any
|
||||
// of the network's acls.
|
||||
for _, networkID := range networksRemoved {
|
||||
acls, err := logic.ListAclsByNetwork(networkID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, acl := range acls {
|
||||
var hasGroupSrc bool
|
||||
newAclSrc := make([]models.AclPolicyTag, 0)
|
||||
for _, src := range acl.Src {
|
||||
if src.ID == models.UserGroupAclID && src.Value == userGroup.ID.String() {
|
||||
hasGroupSrc = true
|
||||
} else {
|
||||
newAclSrc = append(newAclSrc, src)
|
||||
}
|
||||
}
|
||||
|
||||
if hasGroupSrc {
|
||||
if len(newAclSrc) == 0 {
|
||||
// no other src exists, delete acl.
|
||||
_ = logic.DeleteAcl(acl)
|
||||
} else {
|
||||
// other sources exist, update acl.
|
||||
acl.Src = newAclSrc
|
||||
_ = logic.UpsertAcl(acl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// reset configs for service user
|
||||
go proLogic.UpdatesUserGwAccessOnGrpUpdates(currUserG.NetworkRoles, userGroup.NetworkRoles)
|
||||
logic.ReturnSuccessResponseWithJson(w, r, userGroup, "updated user group")
|
||||
|
@ -658,6 +747,39 @@ func deleteUserGroup(w http.ResponseWriter, r *http.Request) {
|
|||
},
|
||||
Origin: models.Dashboard,
|
||||
})
|
||||
|
||||
go func() {
|
||||
for networkID := range userG.NetworkRoles {
|
||||
acls, err := logic.ListAclsByNetwork(networkID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, acl := range acls {
|
||||
var hasGroupSrc bool
|
||||
newAclSrc := make([]models.AclPolicyTag, 0)
|
||||
for _, src := range acl.Src {
|
||||
if src.ID == models.UserGroupAclID && src.Value == userG.ID.String() {
|
||||
hasGroupSrc = true
|
||||
} else {
|
||||
newAclSrc = append(newAclSrc, src)
|
||||
}
|
||||
}
|
||||
|
||||
if hasGroupSrc {
|
||||
if len(newAclSrc) == 0 {
|
||||
// no other src exists, delete acl.
|
||||
_ = logic.DeleteAcl(acl)
|
||||
} else {
|
||||
// other sources exist, update acl.
|
||||
acl.Src = newAclSrc
|
||||
_ = logic.UpsertAcl(acl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go proLogic.UpdatesUserGwAccessOnGrpUpdates(userG.NetworkRoles, make(map[models.NetworkID]map[models.UserRoleID]struct{}))
|
||||
logic.ReturnSuccessResponseWithJson(w, r, nil, "deleted user group")
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ func InitPro() {
|
|||
logic.MigrateToUUIDs = proLogic.MigrateToUUIDs
|
||||
logic.IntialiseGroups = proLogic.UserGroupsInit
|
||||
logic.AddGlobalNetRolesToAdmins = proLogic.AddGlobalNetRolesToAdmins
|
||||
logic.ListUserGroups = proLogic.ListUserGroups
|
||||
logic.GetUserGroupsInNetwork = proLogic.GetUserGroupsInNetwork
|
||||
logic.GetUserGroup = proLogic.GetUserGroup
|
||||
logic.GetNodeStatus = proLogic.GetNodeStatus
|
||||
|
|
Loading…
Add table
Reference in a new issue