Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add multi RBAC assignment support #3865

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions avm/ptn/authorization/policy-assignment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ module policyAssignment 'br/public:avm/ptn/authorization/policy-assignment:<vers
name: 'apamgmax001'
policyDefinitionId: '/providers/Microsoft.Authorization/policySetDefinitions/39a366e6-fdde-4f41-bbf8-3757f46d1611'
// Non-required parameters
additionalManagementGroupsIDsToAssignRbacTo: [
'<name>'
]
description: '[Description] Policy Assignment at the management group scope'
displayName: '[Display Name] Policy Assignment at the management group scope'
enforcementMode: 'DoNotEnforce'
Expand Down Expand Up @@ -217,6 +220,11 @@ module policyAssignment 'br/public:avm/ptn/authorization/policy-assignment:<vers
"value": "/providers/Microsoft.Authorization/policySetDefinitions/39a366e6-fdde-4f41-bbf8-3757f46d1611"
},
// Non-required parameters
"additionalManagementGroupsIDsToAssignRbacTo": {
"value": [
"<name>"
]
},
"description": {
"value": "[Description] Policy Assignment at the management group scope"
},
Expand Down Expand Up @@ -325,6 +333,9 @@ using 'br/public:avm/ptn/authorization/policy-assignment:<version>'
param name = 'apamgmax001'
param policyDefinitionId = '/providers/Microsoft.Authorization/policySetDefinitions/39a366e6-fdde-4f41-bbf8-3757f46d1611'
// Non-required parameters
param additionalManagementGroupsIDsToAssignRbacTo = [
'<name>'
]
param description = '[Description] Policy Assignment at the management group scope'
param displayName = '[Display Name] Policy Assignment at the management group scope'
param enforcementMode = 'DoNotEnforce'
Expand Down Expand Up @@ -1167,6 +1178,7 @@ param userAssignedIdentityId = '<userAssignedIdentityId>'

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`additionalManagementGroupsIDsToAssignRbacTo`](#parameter-additionalmanagementgroupsidstoassignrbacto) | array | An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity. |
| [`description`](#parameter-description) | string | This message will be part of response in case of policy violation. |
| [`displayName`](#parameter-displayname) | string | The display name of the policy assignment. Maximum length is 128 characters. |
| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. |
Expand Down Expand Up @@ -1199,6 +1211,14 @@ Specifies the ID of the policy definition or policy set definition being assigne
- Required: Yes
- Type: string

### Parameter: `additionalManagementGroupsIDsToAssignRbacTo`

An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity.

- Required: No
- Type: array
- Default: `[]`

### Parameter: `description`

This message will be part of response in case of policy violation.
Expand Down
7 changes: 6 additions & 1 deletion avm/ptn/authorization/policy-assignment/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ param enforcementMode string = 'Default'
@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.')
param managementGroupId string = managementGroup().name

@sys.description('Optional. An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity.')
param additionalManagementGroupsIDsToAssignRbacTo array = []

@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment.')
param subscriptionId string = ''

Expand Down Expand Up @@ -110,13 +113,15 @@ module policyAssignment_mg 'modules/management-group.bicep' = if (empty(subscrip
nonComplianceMessages: !empty(nonComplianceMessages) ? nonComplianceMessages : []
enforcementMode: enforcementMode
notScopes: !empty(notScopes) ? notScopes : []
managementGroupId: managementGroupId
location: location
overrides: !empty(overrides) ? overrides : []
resourceSelectors: !empty(resourceSelectors) ? resourceSelectors : []
additionalManagementGroupsIDsToAssignRbacTo: additionalManagementGroupsIDsToAssignRbacTo
}
}

// Create additional role assignments at different management group scopes if needed

module policyAssignment_sub 'modules/subscription.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) {
name: '${uniqueString(deployment().name, location)}-PolicyAssignment-Sub-Module'
scope: subscription(subscriptionId)
Expand Down
207 changes: 179 additions & 28 deletions avm/ptn/authorization/policy-assignment/main.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
targetScope = 'managementGroup'

@sys.description('Optional. An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity.')
param managementGroupsIDsToAssignRbacTo array = []

@sys.description('Required. The ID Of the Azure Role Definition that is used to assign permissions to the identity. You need to provide the fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.. See https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles for the list IDs for built-in Roles. They must match on what is on the policy definition.')
param roleDefinitionId string

@sys.description('Optional. Location for all resources.')
param location string = deployment().location

@sys.description('Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope.')
@maxLength(24)
param name string

@sys.description('Required. The managed identity principal ID associated with the policy assignment.')
param policyAssignmentIdentityId string

module additionalManagementGroupRoleAssignmentsPerMG 'management-group-additional-rbac-asi.bicep' = [
for mg in managementGroupsIDsToAssignRbacTo: {
name: '${uniqueString(deployment().name, location, roleDefinitionId, name)}-PolicyAssignment-MG-Module-Additional-RBAC'
scope: managementGroup(mg)
params: {
name: name
policyAssignmentIdentityId: policyAssignmentIdentityId
roleDefinitionId: roleDefinitionId
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
targetScope = 'managementGroup'

@sys.description('Required. The ID Of the Azure Role Definition that is used to assign permissions to the identity. You need to provide the fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.. See https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles for the list IDs for built-in Roles. They must match on what is on the policy definition.')
param roleDefinitionId string

@sys.description('Optional. Location for all resources.')
param location string = deployment().location

@sys.description('Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope.')
@maxLength(24)
param name string

@sys.description('Required. The managed identity principal ID associated with the policy assignment.')
param policyAssignmentIdentityId string

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(managementGroup().id, roleDefinitionId, location, name)
properties: {
roleDefinitionId: roleDefinitionId
principalId: policyAssignmentIdentityId
principalType: 'ServicePrincipal'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ param userAssignedIdentityId string = ''
@sys.description('Optional. The IDs Of the Azure Role Definition list that is used to assign permissions to the identity. You need to provide either the fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.. See https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles for the list IDs for built-in Roles. They must match on what is on the policy definition.')
param roleDefinitionIds array = []

@sys.description('Optional. An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity.')
param additionalManagementGroupsIDsToAssignRbacTo array = []

@sys.description('Optional. The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs.')
param metadata object = {}

Expand All @@ -48,9 +51,6 @@ param nonComplianceMessages array = []
])
param enforcementMode string = 'Default'

@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.')
param managementGroupId string = managementGroup().name

@sys.description('Optional. The policy excluded scopes.')
param notScopes array = []

Expand All @@ -63,14 +63,22 @@ param overrides array = []
@sys.description('Optional. The resource selector list to filter policies by resource properties. Facilitates safe deployment practices (SDP) by enabling gradual roll out policy assignments based on factors like resource location, resource type, or whether a resource has a location.')
param resourceSelectors array = []

var identityVar = identity == 'SystemAssigned' ? {
type: identity
} : identity == 'UserAssigned' ? {
type: identity
userAssignedIdentities: {
'${userAssignedIdentityId}': {}
}
} : null
var identityVar = identity == 'SystemAssigned'
? {
type: identity
}
: identity == 'UserAssigned'
? {
type: identity
userAssignedIdentities: {
'${userAssignedIdentityId}': {}
}
}
: null

var finalArrayOfManagementGroupsToAssignRbacTo = identity == 'SystemAssigned'
? union(additionalManagementGroupsIDsToAssignRbacTo, [managementGroup().name])
: []

resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
name: name
Expand All @@ -90,15 +98,17 @@ resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01'
identity: identityVar
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && identity == 'SystemAssigned') {
name: guid(managementGroupId, roleDefinitionId, location, name)
properties: {
roleDefinitionId: roleDefinitionId
principalId: policyAssignment.identity.principalId
principalType: 'ServicePrincipal'
module managementGroupRoleAssignments 'management-group-additional-rbac-asi-def-loop.bicep' = [
for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && !empty(additionalManagementGroupsIDsToAssignRbacTo) && identity == 'SystemAssigned') {
name: '${uniqueString(deployment().name, location, roleDefinitionId, name)}-PolicyAssignment-MG-Module-Additional-RBAC'
params: {
name: name
policyAssignmentIdentityId: policyAssignment.identity.principalId
roleDefinitionId: roleDefinitionId
managementGroupsIDsToAssignRbacTo: finalArrayOfManagementGroupsToAssignRbacTo
}
}
}]

]
@sys.description('Policy Assignment Name.')
output name string = policyAssignment.name

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ param namePrefix string = '#_namePrefix_#'
@description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment. If not provided, will use the current scope for deployment.')
param subscriptionId string = '#_subscriptionId_#'

// ============ //
// Dependencies //
// ============ //

resource additionalMg 'Microsoft.Management/managementGroups@2023-04-01' = {
scope: tenant()
name: '${uniqueString(deployment().name)}-additional-mg'
}

// ============== //
// Test Execution //
// ============== //
Expand All @@ -34,6 +43,9 @@ module testDeployment '../../../main.bicep' = {
identity: 'SystemAssigned'
location: resourceLocation
managementGroupId: last(split(managementGroup().id, '/'))
additionalManagementGroupsIDsToAssignRbacTo: [
additionalMg.name
]
metadata: {
category: 'Security'
version: '1.0'
Expand Down
2 changes: 1 addition & 1 deletion avm/ptn/authorization/policy-assignment/version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://aka.ms/bicep-registry-module-version-file-schema#",
"version": "0.1",
"version": "0.2",
"pathFilters": [
"./main.json"
]
Expand Down
Loading