diff --git a/packages/go/analysis/azure/post.go b/packages/go/analysis/azure/post.go index a5869ba5f7..07b0668a44 100644 --- a/packages/go/analysis/azure/post.go +++ b/packages/go/analysis/azure/post.go @@ -95,6 +95,15 @@ func AuthenticationAdministratorPasswordResetTargetRoles() []string { } } +func AddOwnerTargetRoles() []string { + return []string{ + azure.DirectorySynchronizationAccountsRole, + azure.PartnerTier2SupportRole, + azure.PartnerTier1SupportRole, + azure.HybridIdentityAdministratorRole, + } +} + func UserAdministratorPasswordResetTargetRoles() []string { return []string{ azure.UserAccountAdministratorRole, @@ -131,6 +140,7 @@ func AzurePostProcessedRelationships() []graph.Kind { azure.AZMGAddSecret, azure.AZMGGrantAppRoles, azure.AZMGGrantRole, + azure.AddOwner, } } @@ -809,6 +819,34 @@ func globalAdmins(roleAssignments RoleAssignments, tenant *graph.Node, operation }) } +func addOwners(roleAssignments RoleAssignments, tenant *graph.Node, operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob]) { + operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error { + + if tenantContainsServicePrincipalRelationships, err := fetchTenantContainsRelationships(tx, tenant, azure.ServicePrincipal); err != nil { + return err + } else if tenantContainsAppRelationships, err := fetchTenantContainsRelationships(tx, tenant, azure.App); err != nil { + return err + } else { + targetRelationships := append(tenantContainsServicePrincipalRelationships, tenantContainsAppRelationships...) + iter := roleAssignments.UsersWithRole(AddOwnerTargetRoles()...).Iterator() + for iter.HasNext() { + startNode := iter.Next() + for _, targetRelationship := range targetRelationships { + nextJob := analysis.CreatePostRelationshipJob{ + FromID: graph.ID(startNode), + ToID: targetRelationship.EndID, + Kind: azure.AddOwner, + } + if !channels.Submit(ctx, outC, nextJob) { + return nil + } + } + } + return nil + } + }) +} + func privilegedRoleAdmins(roleAssignments RoleAssignments, tenant *graph.Node, operation analysis.StatTrackedOperation[analysis.CreatePostRelationshipJob]) { operation.Operation.SubmitReader(func(ctx context.Context, tx graph.Transaction, outC chan<- analysis.CreatePostRelationshipJob) error { iter := roleAssignments.PrincipalsWithRole(azure.PrivilegedRoleAdministratorRole).Iterator() @@ -917,6 +955,7 @@ func UserRoleAssignments(ctx context.Context, db graph.Database) (*analysis.Atom privilegedRoleAdmins(roleAssignments, tenant, operation) privilegedAuthAdmins(roleAssignments, tenant, operation) addMembers(roleAssignments, operation) + addOwners(roleAssignments, tenant, operation) } } } diff --git a/packages/go/graphschema/azure/roles.go b/packages/go/graphschema/azure/roles.go index 5cf59c3615..e2d3353156 100644 --- a/packages/go/graphschema/azure/roles.go +++ b/packages/go/graphschema/azure/roles.go @@ -1,17 +1,17 @@ // Copyright 2023 Specter Ops, Inc. -// +// // Licensed under the Apache License, Version 2.0 // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// +// // SPDX-License-Identifier: Apache-2.0 package azure @@ -88,4 +88,5 @@ const ( ContributorRole = "b24988ac-6180-42a0-ab88-20f7382dd24c" AKSContributorRole = "ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8" UsageSummaryReportsReaderRole = "75934031-6c7e-415a-99d7-48dbd49e875e" + HybridIdentityAdministratorRole = "8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2" )