mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-14 04:39:54 +00:00
227 lines
8.0 KiB
Go
227 lines
8.0 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
nbdns "github.com/netbirdio/netbird/dns"
|
|
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
|
|
"github.com/netbirdio/netbird/management/server/store"
|
|
"github.com/netbirdio/netbird/management/server/types"
|
|
"github.com/netbirdio/netbird/route"
|
|
"github.com/netbirdio/netbird/shared/management/status"
|
|
)
|
|
|
|
func validateDeleteGroup(ctx context.Context, transaction store.Store, group *types.Group, userID string, flowGroups []string) error {
|
|
// disable a deleting integration group if the initiator is not an admin service user
|
|
if group.Issued == types.GroupIssuedIntegration {
|
|
executingUser, err := transaction.GetUserByUserID(ctx, store.LockingStrengthNone, userID)
|
|
if err != nil {
|
|
return status.Errorf(status.Internal, "failed to get user")
|
|
}
|
|
if executingUser.Role != types.UserRoleAdmin || !executingUser.IsServiceUser {
|
|
return status.Errorf(status.PermissionDenied, "only service users with admin power can delete integration group")
|
|
}
|
|
}
|
|
|
|
if group.IsGroupAll() {
|
|
return status.Errorf(status.InvalidArgument, "deleting group ALL is not allowed")
|
|
}
|
|
|
|
if len(group.Resources) > 0 {
|
|
return &GroupLinkError{"network resource", group.Resources[0].ID}
|
|
}
|
|
|
|
if slices.Contains(flowGroups, group.ID) {
|
|
return &GroupLinkError{"settings", "traffic event logging"}
|
|
}
|
|
|
|
if isLinked, linkedRoute := isGroupLinkedToRoute(ctx, transaction, group.AccountID, group.ID); isLinked {
|
|
return &GroupLinkError{"route", string(linkedRoute.NetID)}
|
|
}
|
|
|
|
if isLinked, linkedDns := isGroupLinkedToDns(ctx, transaction, group.AccountID, group.ID); isLinked {
|
|
return &GroupLinkError{"name server groups", linkedDns.Name}
|
|
}
|
|
|
|
if isLinked, linkedPolicy := isGroupLinkedToPolicy(ctx, transaction, group.AccountID, group.ID); isLinked {
|
|
return &GroupLinkError{"policy", linkedPolicy.Name}
|
|
}
|
|
|
|
if isLinked, linkedSetupKey := isGroupLinkedToSetupKey(ctx, transaction, group.AccountID, group.ID); isLinked {
|
|
return &GroupLinkError{"setup key", linkedSetupKey.Name}
|
|
}
|
|
|
|
if isLinked, linkedUser := isGroupLinkedToUser(ctx, transaction, group.AccountID, group.ID); isLinked {
|
|
return &GroupLinkError{"user", linkedUser.Id}
|
|
}
|
|
|
|
if isLinked, linkedRouter := isGroupLinkedToNetworkRouter(ctx, transaction, group.AccountID, group.ID); isLinked {
|
|
return &GroupLinkError{"network router", linkedRouter.ID}
|
|
}
|
|
|
|
return checkGroupLinkedToSettings(ctx, transaction, group)
|
|
}
|
|
|
|
// checkGroupLinkedToSettings verifies if a group is linked to any settings in the account.
|
|
func checkGroupLinkedToSettings(ctx context.Context, transaction store.Store, group *types.Group) error {
|
|
dnsSettings, err := transaction.GetAccountDNSSettings(ctx, store.LockingStrengthNone, group.AccountID)
|
|
if err != nil {
|
|
return status.Errorf(status.Internal, "failed to get DNS settings")
|
|
}
|
|
|
|
if slices.Contains(dnsSettings.DisabledManagementGroups, group.ID) {
|
|
return &GroupLinkError{"disabled DNS management groups", group.Name}
|
|
}
|
|
|
|
settings, err := transaction.GetAccountSettings(ctx, store.LockingStrengthNone, group.AccountID)
|
|
if err != nil {
|
|
return status.Errorf(status.Internal, "failed to get account settings")
|
|
}
|
|
|
|
if settings.Extra != nil && slices.Contains(settings.Extra.IntegratedValidatorGroups, group.ID) {
|
|
return &GroupLinkError{"integrated validator", group.Name}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// isGroupLinkedToRoute checks if a group is linked to any route in the account.
|
|
func isGroupLinkedToRoute(ctx context.Context, transaction store.Store, accountID string, groupID string) (bool, *route.Route) {
|
|
routes, err := transaction.GetAccountRoutes(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("error retrieving routes while checking group linkage: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
for _, r := range routes {
|
|
isLinked := slices.Contains(r.Groups, groupID) ||
|
|
slices.Contains(r.PeerGroups, groupID) ||
|
|
slices.Contains(r.AccessControlGroups, groupID)
|
|
if isLinked {
|
|
return true, r
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// isGroupLinkedToPolicy checks if a group is linked to any policy in the account.
|
|
func isGroupLinkedToPolicy(ctx context.Context, transaction store.Store, accountID string, groupID string) (bool, *types.Policy) {
|
|
policies, err := transaction.GetAccountPolicies(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("error retrieving policies while checking group linkage: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
for _, policy := range policies {
|
|
for _, rule := range policy.Rules {
|
|
if slices.Contains(rule.Sources, groupID) || slices.Contains(rule.Destinations, groupID) {
|
|
return true, policy
|
|
}
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// isGroupLinkedToDns checks if a group is linked to any nameserver group in the account.
|
|
func isGroupLinkedToDns(ctx context.Context, transaction store.Store, accountID string, groupID string) (bool, *nbdns.NameServerGroup) {
|
|
nameServerGroups, err := transaction.GetAccountNameServerGroups(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("error retrieving name server groups while checking group linkage: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
for _, dns := range nameServerGroups {
|
|
for _, g := range dns.Groups {
|
|
if g == groupID {
|
|
return true, dns
|
|
}
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
// isGroupLinkedToSetupKey checks if a group is linked to any setup key in the account.
|
|
func isGroupLinkedToSetupKey(ctx context.Context, transaction store.Store, accountID string, groupID string) (bool, *types.SetupKey) {
|
|
setupKeys, err := transaction.GetAccountSetupKeys(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("error retrieving setup keys while checking group linkage: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
for _, setupKey := range setupKeys {
|
|
if slices.Contains(setupKey.AutoGroups, groupID) {
|
|
return true, setupKey
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// isGroupLinkedToUser checks if a group is linked to any user in the account.
|
|
func isGroupLinkedToUser(ctx context.Context, transaction store.Store, accountID string, groupID string) (bool, *types.User) {
|
|
users, err := transaction.GetAccountUsers(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("error retrieving users while checking group linkage: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
for _, user := range users {
|
|
if slices.Contains(user.AutoGroups, groupID) {
|
|
return true, user
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// isGroupLinkedToNetworkRouter checks if a group is linked to any network router in the account.
|
|
func isGroupLinkedToNetworkRouter(ctx context.Context, transaction store.Store, accountID string, groupID string) (bool, *routerTypes.NetworkRouter) {
|
|
routers, err := transaction.GetNetworkRoutersByAccountID(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
log.WithContext(ctx).Errorf("error retrieving network routers while checking group linkage: %v", err)
|
|
return false, nil
|
|
}
|
|
|
|
for _, router := range routers {
|
|
if slices.Contains(router.PeerGroups, groupID) {
|
|
return true, router
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// areGroupChangesAffectPeers checks if any changes to the specified groups will affect peers.
|
|
func areGroupChangesAffectPeers(ctx context.Context, transaction store.Store, accountID string, groupIDs []string) (bool, error) {
|
|
if len(groupIDs) == 0 {
|
|
return false, nil
|
|
}
|
|
|
|
dnsSettings, err := transaction.GetAccountDNSSettings(ctx, store.LockingStrengthNone, accountID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
for _, groupID := range groupIDs {
|
|
if slices.Contains(dnsSettings.DisabledManagementGroups, groupID) {
|
|
return true, nil
|
|
}
|
|
if linked, _ := isGroupLinkedToDns(ctx, transaction, accountID, groupID); linked {
|
|
return true, nil
|
|
}
|
|
if linked, _ := isGroupLinkedToPolicy(ctx, transaction, accountID, groupID); linked {
|
|
return true, nil
|
|
}
|
|
if linked, _ := isGroupLinkedToRoute(ctx, transaction, accountID, groupID); linked {
|
|
return true, nil
|
|
}
|
|
if linked, _ := isGroupLinkedToNetworkRouter(ctx, transaction, accountID, groupID); linked {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return false, nil
|
|
}
|