diff --git a/avm/ptn/authorization/policy-assignment/README.md b/avm/ptn/authorization/policy-assignment/README.md index 67d28183ca..72120281ca 100644 --- a/avm/ptn/authorization/policy-assignment/README.md +++ b/avm/ptn/authorization/policy-assignment/README.md @@ -132,6 +132,12 @@ module policyAssignment 'br/public:avm/ptn/authorization/policy-assignment:' ] + additionalResourceGroupResourceIDsToAssignRbacTo: [ + '' + ] + additionalSubscriptionIDsToAssignRbacTo: [ + '' + ] description: '[Description] Policy Assignment at the management group scope' displayName: '[Display Name] Policy Assignment at the management group scope' enforcementMode: 'DoNotEnforce' @@ -149,7 +155,7 @@ module policyAssignment 'br/public:avm/ptn/authorization/policy-assignment:/resourceGroups/validation-rg' + '' ] overrides: [ { @@ -225,6 +231,16 @@ module policyAssignment 'br/public:avm/ptn/authorization/policy-assignment:" ] }, + "additionalResourceGroupResourceIDsToAssignRbacTo": { + "value": [ + "" + ] + }, + "additionalSubscriptionIDsToAssignRbacTo": { + "value": [ + "" + ] + }, "description": { "value": "[Description] Policy Assignment at the management group scope" }, @@ -259,7 +275,7 @@ module policyAssignment 'br/public:avm/ptn/authorization/policy-assignment:/resourceGroups/validation-rg" + "" ] }, "overrides": { @@ -336,6 +352,12 @@ param policyDefinitionId = '/providers/Microsoft.Authorization/policySetDefiniti param additionalManagementGroupsIDsToAssignRbacTo = [ '' ] +param additionalResourceGroupResourceIDsToAssignRbacTo = [ + '' +] +param additionalSubscriptionIDsToAssignRbacTo = [ + '' +] param description = '[Description] Policy Assignment at the management group scope' param displayName = '[Display Name] Policy Assignment at the management group scope' param enforcementMode = 'DoNotEnforce' @@ -353,7 +375,7 @@ param nonComplianceMessages = [ } ] param notScopes = [ - '/subscriptions//resourceGroups/validation-rg' + '' ] param overrides = [ { @@ -1179,6 +1201,8 @@ param 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. | +| [`additionalResourceGroupResourceIDsToAssignRbacTo`](#parameter-additionalresourcegroupresourceidstoassignrbacto) | array | An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments. | +| [`additionalSubscriptionIDsToAssignRbacTo`](#parameter-additionalsubscriptionidstoassignrbacto) | array | An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments. | | [`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. | @@ -1219,6 +1243,22 @@ An array of additional management group IDs to assign RBAC to for the policy ass - Type: array - Default: `[]` +### Parameter: `additionalResourceGroupResourceIDsToAssignRbacTo` + +An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `additionalSubscriptionIDsToAssignRbacTo` + +An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments. + +- Required: No +- Type: array +- Default: `[]` + ### Parameter: `description` This message will be part of response in case of policy violation. diff --git a/avm/ptn/authorization/policy-assignment/main.bicep b/avm/ptn/authorization/policy-assignment/main.bicep index 94aeafcef7..856613eded 100644 --- a/avm/ptn/authorization/policy-assignment/main.bicep +++ b/avm/ptn/authorization/policy-assignment/main.bicep @@ -53,6 +53,12 @@ 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. An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments.') +param additionalSubscriptionIDsToAssignRbacTo array = [] + +@sys.description('Optional. An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments.') +param additionalResourceGroupResourceIDsToAssignRbacTo array = [] + @sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment.') param subscriptionId string = '' @@ -117,6 +123,8 @@ module policyAssignment_mg 'modules/management-group.bicep' = if (empty(subscrip overrides: !empty(overrides) ? overrides : [] resourceSelectors: !empty(resourceSelectors) ? resourceSelectors : [] additionalManagementGroupsIDsToAssignRbacTo: additionalManagementGroupsIDsToAssignRbacTo + additionalSubscriptionIDsToAssignRbacTo: additionalSubscriptionIDsToAssignRbacTo + additionalResourceGroupResourceIDsToAssignRbacTo: additionalResourceGroupResourceIDsToAssignRbacTo } } diff --git a/avm/ptn/authorization/policy-assignment/main.json b/avm/ptn/authorization/policy-assignment/main.json index 165a0150f0..caa17d4bf9 100644 --- a/avm/ptn/authorization/policy-assignment/main.json +++ b/avm/ptn/authorization/policy-assignment/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.92.45157", - "templateHash": "11930294311655684795" + "version": "0.32.4.45862", + "templateHash": "3902127955131309221" }, "name": "Policy Assignments (All scopes)", "description": "This module deploys a Policy Assignment at a Management Group, Subscription or Resource Group scope.", @@ -111,6 +111,20 @@ "description": "Optional. An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity." } }, + "additionalSubscriptionIDsToAssignRbacTo": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments." + } + }, + "additionalResourceGroupResourceIDsToAssignRbacTo": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments." + } + }, "subscriptionId": { "type": "string", "defaultValue": "", @@ -225,6 +239,12 @@ "resourceSelectors": "[if(not(empty(parameters('resourceSelectors'))), createObject('value', parameters('resourceSelectors')), createObject('value', createArray()))]", "additionalManagementGroupsIDsToAssignRbacTo": { "value": "[parameters('additionalManagementGroupsIDsToAssignRbacTo')]" + }, + "additionalSubscriptionIDsToAssignRbacTo": { + "value": "[parameters('additionalSubscriptionIDsToAssignRbacTo')]" + }, + "additionalResourceGroupResourceIDsToAssignRbacTo": { + "value": "[parameters('additionalResourceGroupResourceIDsToAssignRbacTo')]" } }, "template": { @@ -233,8 +253,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.92.45157", - "templateHash": "5042119714141428580" + "version": "0.32.4.45862", + "templateHash": "7784495768661856271" }, "name": "Policy Assignments (Management Group scope)", "description": "This module deploys a Policy Assignment at a Management Group scope.", @@ -309,6 +329,20 @@ "description": "Optional. An array of additional management group IDs to assign RBAC to for the policy assignment if it has an identity." } }, + "additionalSubscriptionIDsToAssignRbacTo": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments." + } + }, + "additionalResourceGroupResourceIDsToAssignRbacTo": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments." + } + }, "metadata": { "type": "object", "defaultValue": {}, @@ -422,8 +456,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.92.45157", - "templateHash": "11309645875744678880" + "version": "0.32.4.45862", + "templateHash": "9631038445585845349" } }, "parameters": { @@ -494,8 +528,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.92.45157", - "templateHash": "3019736989546376452" + "version": "0.32.4.45862", + "templateHash": "9140403539470176881" } }, "parameters": { @@ -547,6 +581,328 @@ "dependsOn": [ "[extensionResourceId(managementGroup().id, 'Microsoft.Authorization/policyAssignments', parameters('name'))]" ] + }, + { + "copy": { + "name": "additionalSubscriptionRoleAssignments", + "count": "[length(parameters('roleDefinitionIds'))]" + }, + "condition": "[and(and(not(empty(parameters('roleDefinitionIds'))), not(empty(parameters('additionalSubscriptionIDsToAssignRbacTo')))), equals(parameters('identity'), 'SystemAssigned'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PolicyAssignment-MG-Module-Additional-RBAC-Subs', uniqueString(deployment().name, parameters('location'), parameters('roleDefinitionIds')[copyIndex()], parameters('name')))]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('name')]" + }, + "policyAssignmentIdentityId": { + "value": "[reference(extensionResourceId(managementGroup().id, 'Microsoft.Authorization/policyAssignments', parameters('name')), '2022-06-01', 'full').identity.principalId]" + }, + "roleDefinitionId": { + "value": "[parameters('roleDefinitionIds')[copyIndex()]]" + }, + "subscriptionIDsToAssignRbacTo": { + "value": "[parameters('additionalSubscriptionIDsToAssignRbacTo')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "5868976721767457523" + } + }, + "parameters": { + "subscriptionIDsToAssignRbacTo": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments." + } + }, + "roleDefinitionId": { + "type": "string", + "metadata": { + "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." + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "name": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope." + } + }, + "policyAssignmentIdentityId": { + "type": "string", + "metadata": { + "description": "Required. The managed identity principal ID associated with the policy assignment." + } + } + }, + "resources": [ + { + "copy": { + "name": "additionalSubscriptionRoleAssignmentsPerSub", + "count": "[length(parameters('subscriptionIDsToAssignRbacTo'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PolicyAssignment-MG-Module-RBAC-Sub-{1}', uniqueString(deployment().name, parameters('location'), parameters('roleDefinitionId'), parameters('name')), substring(parameters('subscriptionIDsToAssignRbacTo')[copyIndex()], 0, 8))]", + "subscriptionId": "[parameters('subscriptionIDsToAssignRbacTo')[copyIndex()]]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('name')]" + }, + "policyAssignmentIdentityId": { + "value": "[parameters('policyAssignmentIdentityId')]" + }, + "roleDefinitionId": { + "value": "[parameters('roleDefinitionId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "1856107527131838082" + } + }, + "parameters": { + "roleDefinitionId": { + "type": "string", + "metadata": { + "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." + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "name": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope." + } + }, + "policyAssignmentIdentityId": { + "type": "string", + "metadata": { + "description": "Required. The managed identity principal ID associated with the policy assignment." + } + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[guid(subscription().id, parameters('roleDefinitionId'), parameters('location'), parameters('name'))]", + "properties": { + "roleDefinitionId": "[parameters('roleDefinitionId')]", + "principalId": "[parameters('policyAssignmentIdentityId')]", + "principalType": "ServicePrincipal" + } + } + ] + } + } + } + ] + } + }, + "dependsOn": [ + "[extensionResourceId(managementGroup().id, 'Microsoft.Authorization/policyAssignments', parameters('name'))]" + ] + }, + { + "copy": { + "name": "additionalResourceGroupRoleAssignments", + "count": "[length(parameters('roleDefinitionIds'))]" + }, + "condition": "[and(and(not(empty(parameters('roleDefinitionIds'))), not(empty(parameters('additionalResourceGroupResourceIDsToAssignRbacTo')))), equals(parameters('identity'), 'SystemAssigned'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PolicyAssignment-MG-Module-Additional-RBAC-RGs', uniqueString(deployment().name, parameters('location'), parameters('roleDefinitionIds')[copyIndex()], parameters('name')))]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('name')]" + }, + "policyAssignmentIdentityId": { + "value": "[reference(extensionResourceId(managementGroup().id, 'Microsoft.Authorization/policyAssignments', parameters('name')), '2022-06-01', 'full').identity.principalId]" + }, + "roleDefinitionId": { + "value": "[parameters('roleDefinitionIds')[copyIndex()]]" + }, + "resourceGroupResourceIDsToAssignRbacTo": { + "value": "[parameters('additionalResourceGroupResourceIDsToAssignRbacTo')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "12514251766635911763" + } + }, + "parameters": { + "resourceGroupResourceIDsToAssignRbacTo": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments." + } + }, + "roleDefinitionId": { + "type": "string", + "metadata": { + "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." + } + }, + "location": { + "type": "string", + "defaultValue": "[deployment().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "name": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope." + } + }, + "policyAssignmentIdentityId": { + "type": "string", + "metadata": { + "description": "Required. The managed identity principal ID associated with the policy assignment." + } + } + }, + "resources": [ + { + "copy": { + "name": "additionalResourceGroupResourceIDsRoleAssignmentsPerSub", + "count": "[length(parameters('resourceGroupResourceIDsToAssignRbacTo'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PolicyAssignment-MG-Module-RBAC-RG-Sub-{1}', uniqueString(deployment().name, parameters('location'), parameters('roleDefinitionId'), parameters('name'), parameters('resourceGroupResourceIDsToAssignRbacTo')[copyIndex()]), substring(split(parameters('resourceGroupResourceIDsToAssignRbacTo')[copyIndex()], '/')[2], 0, 8))]", + "subscriptionId": "[split(parameters('resourceGroupResourceIDsToAssignRbacTo')[copyIndex()], '/')[2]]", + "resourceGroup": "[split(parameters('resourceGroupResourceIDsToAssignRbacTo')[copyIndex()], '/')[4]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('name')]" + }, + "policyAssignmentIdentityId": { + "value": "[parameters('policyAssignmentIdentityId')]" + }, + "roleDefinitionId": { + "value": "[parameters('roleDefinitionId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "11358116386111113340" + } + }, + "parameters": { + "roleDefinitionId": { + "type": "string", + "metadata": { + "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." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "name": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope." + } + }, + "policyAssignmentIdentityId": { + "type": "string", + "metadata": { + "description": "Required. The managed identity principal ID associated with the policy assignment." + } + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[guid(resourceGroup().id, parameters('roleDefinitionId'), parameters('location'), parameters('name'))]", + "properties": { + "roleDefinitionId": "[parameters('roleDefinitionId')]", + "principalId": "[parameters('policyAssignmentIdentityId')]", + "principalType": "ServicePrincipal" + } + } + ] + } + } + } + ] + } + }, + "dependsOn": [ + "[extensionResourceId(managementGroup().id, 'Microsoft.Authorization/policyAssignments', parameters('name'))]" + ] } ], "outputs": { @@ -632,8 +988,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.92.45157", - "templateHash": "11837811199926553363" + "version": "0.32.4.45862", + "templateHash": "5956652963277088316" }, "name": "Policy Assignments (Subscription scope)", "description": "This module deploys a Policy Assignment at a Subscription scope.", @@ -887,8 +1243,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.31.92.45157", - "templateHash": "14180900151844687910" + "version": "0.32.4.45862", + "templateHash": "15421130529251696480" }, "name": "Policy Assignments (Resource Group scope)", "description": "This module deploys a Policy Assignment at a Resource Group scope.", diff --git a/avm/ptn/authorization/policy-assignment/modules/management-group.bicep b/avm/ptn/authorization/policy-assignment/modules/management-group.bicep index 2c5c25e0c0..5c48dbade3 100644 --- a/avm/ptn/authorization/policy-assignment/modules/management-group.bicep +++ b/avm/ptn/authorization/policy-assignment/modules/management-group.bicep @@ -38,6 +38,12 @@ 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. An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments.') +param additionalSubscriptionIDsToAssignRbacTo array = [] + +@sys.description('Optional. An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments.') +param additionalResourceGroupResourceIDsToAssignRbacTo 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 = {} @@ -109,6 +115,31 @@ module managementGroupRoleAssignments 'management-group-additional-rbac-asi-def- } } ] + +module additionalSubscriptionRoleAssignments 'subscription-additional-rbac-asi-def-loop.bicep' = [ + for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && !empty(additionalSubscriptionIDsToAssignRbacTo) && identity == 'SystemAssigned') { + name: '${uniqueString(deployment().name, location, roleDefinitionId, name)}-PolicyAssignment-MG-Module-Additional-RBAC-Subs' + params: { + name: name + policyAssignmentIdentityId: policyAssignment.identity.principalId + roleDefinitionId: roleDefinitionId + subscriptionIDsToAssignRbacTo: additionalSubscriptionIDsToAssignRbacTo + } + } +] + +module additionalResourceGroupRoleAssignments 'resource-group-additional-rbac-asi-def-loop.bicep' = [ + for roleDefinitionId in roleDefinitionIds: if (!empty(roleDefinitionIds) && !empty(additionalResourceGroupResourceIDsToAssignRbacTo) && identity == 'SystemAssigned') { + name: '${uniqueString(deployment().name, location, roleDefinitionId, name)}-PolicyAssignment-MG-Module-Additional-RBAC-RGs' + params: { + name: name + policyAssignmentIdentityId: policyAssignment.identity.principalId + roleDefinitionId: roleDefinitionId + resourceGroupResourceIDsToAssignRbacTo: additionalResourceGroupResourceIDsToAssignRbacTo + } + } +] + @sys.description('Policy Assignment Name.') output name string = policyAssignment.name diff --git a/avm/ptn/authorization/policy-assignment/modules/resource-group-additional-rbac-asi-def-loop.bicep b/avm/ptn/authorization/policy-assignment/modules/resource-group-additional-rbac-asi-def-loop.bicep new file mode 100644 index 0000000000..77e778fd02 --- /dev/null +++ b/avm/ptn/authorization/policy-assignment/modules/resource-group-additional-rbac-asi-def-loop.bicep @@ -0,0 +1,29 @@ +targetScope = 'managementGroup' + +@sys.description('Optional. An array of additional Resource Group Resource IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments.') +param resourceGroupResourceIDsToAssignRbacTo 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 additionalResourceGroupResourceIDsRoleAssignmentsPerSub 'resource-group-additional-rbac-asi.bicep' = [ + for rg in resourceGroupResourceIDsToAssignRbacTo: { + name: '${uniqueString(deployment().name, location, roleDefinitionId, name, rg)}-PolicyAssignment-MG-Module-RBAC-RG-Sub-${substring(split(rg, '/')[2], 0, 8)}' + scope: resourceGroup(split(rg, '/')[2], split(rg, '/')[4]) + params: { + name: name + policyAssignmentIdentityId: policyAssignmentIdentityId + roleDefinitionId: roleDefinitionId + } + } +] diff --git a/avm/ptn/authorization/policy-assignment/modules/resource-group-additional-rbac-asi.bicep b/avm/ptn/authorization/policy-assignment/modules/resource-group-additional-rbac-asi.bicep new file mode 100644 index 0000000000..120f0aa0d8 --- /dev/null +++ b/avm/ptn/authorization/policy-assignment/modules/resource-group-additional-rbac-asi.bicep @@ -0,0 +1,21 @@ +@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 = resourceGroup().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(resourceGroup().id, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignmentIdentityId + principalType: 'ServicePrincipal' + } +} diff --git a/avm/ptn/authorization/policy-assignment/modules/subscription-additional-rbac-asi-def-loop.bicep b/avm/ptn/authorization/policy-assignment/modules/subscription-additional-rbac-asi-def-loop.bicep new file mode 100644 index 0000000000..89576ed7fc --- /dev/null +++ b/avm/ptn/authorization/policy-assignment/modules/subscription-additional-rbac-asi-def-loop.bicep @@ -0,0 +1,29 @@ +targetScope = 'managementGroup' + +@sys.description('Optional. An array of additional Subscription IDs to assign RBAC to for the policy assignment if it has an identity, only supported for Management Group Policy Assignments.') +param subscriptionIDsToAssignRbacTo 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 additionalSubscriptionRoleAssignmentsPerSub 'subscription-additional-rbac-asi.bicep' = [ + for sub in subscriptionIDsToAssignRbacTo: { + name: '${uniqueString(deployment().name, location, roleDefinitionId, name)}-PolicyAssignment-MG-Module-RBAC-Sub-${substring(sub, 0, 8)}' + scope: subscription(sub) + params: { + name: name + policyAssignmentIdentityId: policyAssignmentIdentityId + roleDefinitionId: roleDefinitionId + } + } +] diff --git a/avm/ptn/authorization/policy-assignment/modules/subscription-additional-rbac-asi.bicep b/avm/ptn/authorization/policy-assignment/modules/subscription-additional-rbac-asi.bicep new file mode 100644 index 0000000000..fb980fa244 --- /dev/null +++ b/avm/ptn/authorization/policy-assignment/modules/subscription-additional-rbac-asi.bicep @@ -0,0 +1,23 @@ +targetScope = 'subscription' + +@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(subscription().id, roleDefinitionId, location, name) + properties: { + roleDefinitionId: roleDefinitionId + principalId: policyAssignmentIdentityId + principalType: 'ServicePrincipal' + } +} diff --git a/avm/ptn/authorization/policy-assignment/tests/e2e/mg.max/main.test.bicep b/avm/ptn/authorization/policy-assignment/tests/e2e/mg.max/main.test.bicep index 37f19104d3..b91afcf088 100644 --- a/avm/ptn/authorization/policy-assignment/tests/e2e/mg.max/main.test.bicep +++ b/avm/ptn/authorization/policy-assignment/tests/e2e/mg.max/main.test.bicep @@ -12,6 +12,10 @@ param serviceShort string = 'apamgmax' @description('Optional. The location to deploy resources to.') param resourceLocation string = deployment().location +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-authorization.policyassignments-${serviceShort}-rg' + @description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' @@ -27,6 +31,15 @@ resource additionalMg 'Microsoft.Management/managementGroups@2023-04-01' = { name: '${uniqueString(deployment().name)}-additional-mg' } +module additionalRsg 'br/public:avm/res/resources/resource-group:0.4.0' = { + scope: subscription(subscriptionId) + name: '${uniqueString(deployment().name, resourceLocation)}-resourceGroup' + params: { + name: resourceGroupName + location: resourceLocation + } +} + // ============== // // Test Execution // // ============== // @@ -46,6 +59,12 @@ module testDeployment '../../../main.bicep' = { additionalManagementGroupsIDsToAssignRbacTo: [ additionalMg.name ] + additionalSubscriptionIDsToAssignRbacTo: [ + subscriptionId + ] + additionalResourceGroupResourceIDsToAssignRbacTo: [ + additionalRsg.outputs.resourceId + ] metadata: { category: 'Security' version: '1.0' @@ -57,7 +76,7 @@ module testDeployment '../../../main.bicep' = { } ] notScopes: [ - '/subscriptions/${subscriptionId}/resourceGroups/validation-rg' + additionalRsg.outputs.resourceId ] parameters: { enableCollectionOfSqlQueriesForSecurityResearch: { diff --git a/avm/ptn/authorization/policy-assignment/version.json b/avm/ptn/authorization/policy-assignment/version.json index daf1a794d9..76049e1c4a 100644 --- a/avm/ptn/authorization/policy-assignment/version.json +++ b/avm/ptn/authorization/policy-assignment/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.2", + "version": "0.3", "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file