Skip to content

Commit

Permalink
feat: add multi RBAC assignment support (#3865)
Browse files Browse the repository at this point in the history
## Description

add multi RBAC assignment support

## Pipeline Reference

<!-- Insert your Pipeline Status Badge below -->

| Pipeline |
| -------- |
|
[![avm.ptn.authorization.policy-assignment](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.ptn.authorization.policy-assignment.yml/badge.svg?branch=feat%2Fadd-multi-rbac-assignment-support)](https://github.com/jtracey93/bicep-registry-modules/actions/workflows/avm.ptn.authorization.policy-assignment.yml)
|

## Type of Change

<!-- Use the checkboxes [x] on the options that are relevant. -->

- [ ] Update to CI Environment or utilities (Non-module affecting
changes)
- [x] Azure Verified Module updates:
- [ ] Bugfix containing backwards-compatible bug fixes, and I have NOT
bumped the MAJOR or MINOR version in `version.json`:
- [ ] Someone has opened a bug report issue, and I have included "Closes
#{bug_report_issue_number}" in the PR description.
- [ ] The bug was found by the module author, and no one has opened an
issue to report it yet.
- [x] Feature update backwards compatible feature updates, and I have
bumped the MINOR version in `version.json`.
- [ ] Breaking changes and I have bumped the MAJOR version in
`version.json`.
  - [ ] Update to documentation

## Checklist

- [x] I'm sure there are no other open Pull Requests for the same
update/change
- [x] I have run `Set-AVMModule` locally to generate the supporting
module files.
- [x] My corresponding pipelines / checks run clean and green without
any errors or warnings

<!-- Please keep up to date with the contribution guide at
https://aka.ms/avm/contribute/bicep -->
  • Loading branch information
jtracey93 authored Dec 2, 2024
1 parent ff7bdfc commit c5a01ec
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 49 deletions.
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

0 comments on commit c5a01ec

Please sign in to comment.