|
| 1 | +targetScope='subscription' |
| 2 | + |
| 3 | +@minLength(1) |
| 4 | +param miPrincipalId string |
| 5 | +@minLength(1) |
| 6 | +param miName string |
| 7 | +@minLength(1) |
| 8 | +param userGroupPrincipalID string |
| 9 | +@minLength(1) |
| 10 | +param userGroupName string |
| 11 | + |
| 12 | +// See: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles |
| 13 | +var roleID = { |
| 14 | + contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' |
| 15 | + kvSecretsUser: '4633458b-17de-408a-b874-0445c86b69e6' // gitleaks:allow |
| 16 | + kvSecretsOfficer: 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7' // gitleaks:allow |
| 17 | + rbacAdmin: 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' |
| 18 | + storageBlobDataContributor: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe' |
| 19 | + storageQueueDataContributor: '974c5e8b-45b9-4653-ba55-5f855dd0fb88' |
| 20 | + AzureConnectedMachineOnboarding: 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7' |
| 21 | +} |
| 22 | + |
| 23 | +// Define role assignments for managed identity |
| 24 | +var miRoleAssignments = [ |
| 25 | + { |
| 26 | + roleName: 'contributor' |
| 27 | + roleId: roleID.contributor |
| 28 | + description: 'Contributor access to subscription' |
| 29 | + } |
| 30 | + { |
| 31 | + roleName: 'kvSecretsUser' |
| 32 | + roleId: roleID.kvSecretsUser |
| 33 | + description: 'kvSecretsUser access to subscription' |
| 34 | + } |
| 35 | + { |
| 36 | + roleName: 'rbacAdmin' |
| 37 | + roleId: roleID.rbacAdmin |
| 38 | + description: 'RBAC Administrator. Restricted to only assign/remove: Storage Blob Data Contributor, Storage Queue Data Contributor, and Azure Connected Machine Onboarding.' |
| 39 | + // Delegated RBAC: This condition restricts the RBAC Administrator to only manage specific roles. |
| 40 | + // This is a security best practice that prevents the identity from granting itself or others sensitive roles like 'Owner' or 'User Access Administrator'. |
| 41 | + condition: '((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/write\'})) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${roleID.storageBlobDataContributor}, ${roleID.storageQueueDataContributor}, ${roleID.AzureConnectedMachineOnboarding}})) AND ((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/delete\'})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${roleID.storageBlobDataContributor}, ${roleID.storageQueueDataContributor}, ${roleID.AzureConnectedMachineOnboarding}}))' |
| 42 | + conditionVersion: '2.0' |
| 43 | + } |
| 44 | +] |
| 45 | + |
| 46 | +// Define role assignments for Entra ID group |
| 47 | +var groupRoleAssignments = [ |
| 48 | + { |
| 49 | + roleName: 'contributor' |
| 50 | + roleId: roleID.contributor |
| 51 | + description: 'Contributor access to subscription' |
| 52 | + } |
| 53 | + { |
| 54 | + roleName: 'kvSecretsOfficer' |
| 55 | + roleId: roleID.kvSecretsOfficer |
| 56 | + description: 'kvSecretsOfficer access to subscription' |
| 57 | + } |
| 58 | + { |
| 59 | + roleName: 'rbacAdmin' |
| 60 | + roleId: roleID.rbacAdmin |
| 61 | + description: 'RBAC Administrator. Restricted to only assign/remove: Storage Blob Data Contributor, Storage Queue Data Contributor, and Azure Connected Machine Onboarding.' |
| 62 | + // Delegated RBAC: This condition restricts the RBAC Administrator to only manage specific roles. |
| 63 | + // This is a security best practice that prevents the identity from granting itself or others sensitive roles like 'Owner' or 'User Access Administrator'. |
| 64 | + condition: '((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/write\'})) OR (@Request[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${roleID.storageBlobDataContributor}, ${roleID.storageQueueDataContributor}, ${roleID.AzureConnectedMachineOnboarding}})) AND ((!(ActionMatches{\'Microsoft.Authorization/roleAssignments/delete\'})) OR (@Resource[Microsoft.Authorization/roleAssignments:RoleDefinitionId] ForAnyOfAnyValues:GuidEquals {${roleID.storageBlobDataContributor}, ${roleID.storageQueueDataContributor}, ${roleID.AzureConnectedMachineOnboarding}}))' |
| 65 | + conditionVersion: '2.0' |
| 66 | + } |
| 67 | +] |
| 68 | + |
| 69 | +// This creates one resource for each item in the miRoleAssignments array |
| 70 | +resource miRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in miRoleAssignments: { |
| 71 | + // guid() ensures unique names for each assignment |
| 72 | + name: guid(subscription().subscriptionId, miPrincipalId, role.roleName) |
| 73 | + properties: { |
| 74 | + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role.roleId) |
| 75 | + principalId: miPrincipalId |
| 76 | + principalType: 'ServicePrincipal' |
| 77 | + description: '${miName} ${role.description}' |
| 78 | + // Conditionally include the 'condition' property only if it exists in the role object |
| 79 | + condition: role.?condition |
| 80 | + conditionVersion: role.?conditionVersion |
| 81 | + } |
| 82 | +}] |
| 83 | + |
| 84 | + |
| 85 | +// This creates one resource for each item in the groupRoleAssignments array |
| 86 | +resource groupRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in groupRoleAssignments: { |
| 87 | + name: guid(subscription().subscriptionId, userGroupPrincipalID, role.roleName) |
| 88 | + properties: { |
| 89 | + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role.roleId) |
| 90 | + principalId: userGroupPrincipalID |
| 91 | + principalType: 'Group' |
| 92 | + description: '${userGroupName} ${role.description}' |
| 93 | + condition: role.?condition |
| 94 | + conditionVersion: role.?conditionVersion |
| 95 | + } |
| 96 | +}] |
0 commit comments