From 0e689f66aca64ac65aaf52f1cfdfa32e484bd4b0 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:45:12 +0000 Subject: [PATCH 1/6] bootstrap module set-admmodule --- .../authorization/role-definition/README.md | 194 ++++++++++++++++++ .../authorization/role-definition/main.bicep | 65 ++++++ .../authorization/role-definition/main.json | 58 ++++++ .../tests/e2e/defaults/main.test.bicep | 48 +++++ .../tests/e2e/waf-aligned/main.test.bicep | 48 +++++ .../role-definition/version.json | 7 + 6 files changed, 420 insertions(+) create mode 100644 avm/ptn/authorization/role-definition/README.md create mode 100644 avm/ptn/authorization/role-definition/main.bicep create mode 100644 avm/ptn/authorization/role-definition/main.json create mode 100644 avm/ptn/authorization/role-definition/tests/e2e/defaults/main.test.bicep create mode 100644 avm/ptn/authorization/role-definition/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/ptn/authorization/role-definition/version.json diff --git a/avm/ptn/authorization/role-definition/README.md b/avm/ptn/authorization/role-definition/README.md new file mode 100644 index 0000000000..749cc6e4a8 --- /dev/null +++ b/avm/ptn/authorization/role-definition/README.md @@ -0,0 +1,194 @@ +# `[Authorization/RoleDefinition]` + + + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Data Collection](#Data-Collection) + +## Resource Types + +_None_ + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/ptn/authorization/role-definition:`. + +- [Defaults](#example-1-defaults) +- [Waf-Aligned](#example-2-waf-aligned) + +### Example 1: _Defaults_ + +
+ +via Bicep module + +```bicep +module roleDefinition 'br/public:avm/ptn/authorization/role-definition:' = { + name: 'roleDefinitionDeployment' + params: { + // Required parameters + name: 'arddef001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "arddef001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/authorization/role-definition:' + +// Required parameters +param name = 'arddef001' +// Non-required parameters +param location = '' +``` + +
+

+ +### Example 2: _Waf-Aligned_ + +

+ +via Bicep module + +```bicep +module roleDefinition 'br/public:avm/ptn/authorization/role-definition:' = { + name: 'roleDefinitionDeployment' + params: { + // Required parameters + name: 'ardwaf001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "ardwaf001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/ptn/authorization/role-definition:' + +// Required parameters +param name = 'ardwaf001' +// Non-required parameters +param location = '' +``` + +
+

+ +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the resource to create. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`location`](#parameter-location) | string | Location for all Resources. | + +### Parameter: `name` + +Name of the resource to create. + +- Required: Yes +- Type: string + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location for all Resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +## Outputs + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/ptn/authorization/role-definition/main.bicep b/avm/ptn/authorization/role-definition/main.bicep new file mode 100644 index 0000000000..593767ccc3 --- /dev/null +++ b/avm/ptn/authorization/role-definition/main.bicep @@ -0,0 +1,65 @@ +metadata name = '' +metadata description = '' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the resource to create.') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +// +// Add your parameters here +// + +// ============== // +// Resources // +// ============== // + +#disable-next-line no-deployments-resources +resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { + name: '46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +// +// Add your resources here +// + +// ============ // +// Outputs // +// ============ // + +// Add your outputs here + +// @description('The resource ID of the resource.') +// output resourceId string = .id + +// @description('The name of the resource.') +// output name string = .name + +// @description('The location the resource was deployed into.') +// output location string = .location + +// ================ // +// Definitions // +// ================ // +// +// Add your User-defined-types here, if any +// diff --git a/avm/ptn/authorization/role-definition/main.json b/avm/ptn/authorization/role-definition/main.json new file mode 100644 index 0000000000..a62736faa4 --- /dev/null +++ b/avm/ptn/authorization/role-definition/main.json @@ -0,0 +1,58 @@ +{ + "$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": "14578551070113584879" + }, + "name": "", + "description": "", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the resource to create." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "resources": [ + { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/avm/ptn/authorization/role-definition/tests/e2e/defaults/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..4b1931b306 --- /dev/null +++ b/avm/ptn/authorization/role-definition/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,48 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = 'arddef' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + // You parameters go here + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + } + } +] diff --git a/avm/ptn/authorization/role-definition/tests/e2e/waf-aligned/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..3e71c58018 --- /dev/null +++ b/avm/ptn/authorization/role-definition/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,48 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' +param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test +param serviceShort string = 'ardwaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + // You parameters go here + name: '${namePrefix}${serviceShort}001' + location: resourceLocation + } + } +] diff --git a/avm/ptn/authorization/role-definition/version.json b/avm/ptn/authorization/role-definition/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/ptn/authorization/role-definition/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 81ce8d7d4da1827fbcbd41e832664df1812e8920 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:09:41 +0000 Subject: [PATCH 2/6] Create avm.ptn.authorization.role-definition.yml --- .../avm.ptn.authorization.role-definition.yml | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 .github/workflows/avm.ptn.authorization.role-definition.yml diff --git a/.github/workflows/avm.ptn.authorization.role-definition.yml b/.github/workflows/avm.ptn.authorization.role-definition.yml new file mode 100644 index 0000000000..3026e36233 --- /dev/null +++ b/.github/workflows/avm.ptn.authorization.role-definition.yml @@ -0,0 +1,88 @@ +name: "avm.ptn.authorization.role-definition" + +on: + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.ptn.authorization.role-definition.yml" + - "avm/ptn/authorization/role-definition/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/ptn/authorization/role-definition" + workflowPath: ".github/workflows/avm.ptn.authorization.role-definition.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From a8505205e30b571b8099b56b87734a7c5b074316 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:10:01 +0000 Subject: [PATCH 3/6] feat: Add role definition module and workflow for management group authorization --- .github/CODEOWNERS | 1 + .../avm.ptn.authorization.role-definition.yml | 88 +++++++++++++++++ .../authorization/role-definition/main.bicep | 95 +++++++++++++------ .../{defaults => mg.default}/main.test.bicep | 0 .../main.test.bicep | 0 5 files changed, 156 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/avm.ptn.authorization.role-definition.yml rename avm/ptn/authorization/role-definition/tests/e2e/{defaults => mg.default}/main.test.bicep (100%) rename avm/ptn/authorization/role-definition/tests/e2e/{waf-aligned => mg.loadJson}/main.test.bicep (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cc29bb9964..ea54078099 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,6 +8,7 @@ /avm/ptn/authorization/policy-assignment/ @Azure/avm-ptn-authorization-policyassignment-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/authorization/resource-role-assignment/ @Azure/avm-ptn-authorization-resourceroleassignment-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/ptn/authorization/role-assignment/ @Azure/avm-ptn-authorization-roleassignment-module-owners-bicep @Azure/avm-module-reviewers-bicep +/avm/ptn/authorization/role-definition/ @Azure/avm-ptn-authorization-roledefinition-module-owners-bicep @Azure/avm-module-reviewers-bicep #/avm/ptn/avd-lza/insights/ @Azure/avm-ptn-avd-lza-insights-module-owners-bicep @Azure/avm-module-reviewers-bicep #/avm/ptn/avd-lza/management-plane/ @Azure/avm-ptn-avd-lza-managementplane-module-owners-bicep @Azure/avm-module-reviewers-bicep #/avm/ptn/avd-lza/networking/ @Azure/avm-ptn-avd-lza-networking-module-owners-bicep @Azure/avm-module-reviewers-bicep diff --git a/.github/workflows/avm.ptn.authorization.role-definition.yml b/.github/workflows/avm.ptn.authorization.role-definition.yml new file mode 100644 index 0000000000..3026e36233 --- /dev/null +++ b/.github/workflows/avm.ptn.authorization.role-definition.yml @@ -0,0 +1,88 @@ +name: "avm.ptn.authorization.role-definition" + +on: + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.ptn.authorization.role-definition.yml" + - "avm/ptn/authorization/role-definition/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/ptn/authorization/role-definition" + workflowPath: ".github/workflows/avm.ptn.authorization.role-definition.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/ptn/authorization/role-definition/main.bicep b/avm/ptn/authorization/role-definition/main.bicep index 593767ccc3..6e6c732f3f 100644 --- a/avm/ptn/authorization/role-definition/main.bicep +++ b/avm/ptn/authorization/role-definition/main.bicep @@ -1,19 +1,17 @@ -metadata name = '' -metadata description = '' -metadata owner = 'Azure/module-maintainers' +metadata name = 'avm/ptn/authorization/role-definition' +metadata description = 'This module deploys a custom role definition to a Management Group.' +metadata owner = '@jtracey93' -@description('Required. Name of the resource to create.') -param name string - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location +targetScope = 'managementGroup' @description('Optional. Enable/Disable usage telemetry for module.') param enableTelemetry bool = true -// -// Add your parameters here -// +@description('Optional. The location of the telemetry deployment to be created. Default is location of deployment.') +param location string = deployment().location + +@description('Required. Array of custom role definitions to create on the management group.') +param roleDefinition roleDefinitionType // ============== // // Resources // @@ -21,7 +19,7 @@ param enableTelemetry bool = true #disable-next-line no-deployments-resources resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { - name: '46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + name: '46d3xbcp.ptn.authorization-roledefinition.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' properties: { mode: 'Incremental' template: { @@ -38,28 +36,69 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } -// -// Add your resources here -// +resource res_roleDefinition_mg 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' = { + name: contains(roleDefinition.name, '-') && length(roleDefinition.name) == 36 && length(split( + roleDefinition.name, + '-' + )) == 5 + ? roleDefinition.name + : guid(roleDefinition.name) + properties: { + roleName: roleDefinition.?roleName ?? roleDefinition.name + description: roleDefinition.?description + type: 'CustomRole' + assignableScopes: roleDefinition.?assignableScopes ?? [ + managementGroup().id + ] + permissions: [ + { + actions: roleDefinition.?actions ?? [] + notActions: roleDefinition.?notActions ?? [] + dataActions: roleDefinition.?dataActions ?? [] + notDataActions: roleDefinition.?notDataActions ?? [] + } + ] + } +} // ============ // // Outputs // // ============ // -// Add your outputs here - -// @description('The resource ID of the resource.') -// output resourceId string = .id - -// @description('The name of the resource.') -// output name string = .name - -// @description('The location the resource was deployed into.') -// output location string = .location +output managementGroupCustomRoleDefinitionIds object = { + resourceId: res_roleDefinition_mg.id + roleDefinitionId: res_roleDefinition_mg.name + displayName: res_roleDefinition_mg.properties.roleName +} // ================ // // Definitions // // ================ // -// -// Add your User-defined-types here, if any -// + +@export() +@description('A type for custom role definition.') +type roleDefinitionType = { + @description('Required. The name of the custom role definition.') + name: string + + @description('Optional. The description of the custom role definition.') + description: string? + + @description('Optional. The assignable scopes of the custom role definition. If not specified, the management group being targeted in the parameter managementGroupName will be used.') + assignableScopes: string[]? + + @description('Optional. The permission actions of the custom role definition.') + actions: string[]? + + @description('Optional. The permission not actions of the custom role definition.') + notActions: string[]? + + @description('Optional. The permission data actions of the custom role definition.') + dataActions: string[]? + + @description('Optional. The permission not data actions of the custom role definition.') + notDataActions: string[]? + + @description('Optional. The display name of the custom role definition. If not specified, the name will be used.') + roleName: string? +} diff --git a/avm/ptn/authorization/role-definition/tests/e2e/defaults/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/mg.default/main.test.bicep similarity index 100% rename from avm/ptn/authorization/role-definition/tests/e2e/defaults/main.test.bicep rename to avm/ptn/authorization/role-definition/tests/e2e/mg.default/main.test.bicep diff --git a/avm/ptn/authorization/role-definition/tests/e2e/waf-aligned/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep similarity index 100% rename from avm/ptn/authorization/role-definition/tests/e2e/waf-aligned/main.test.bicep rename to avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep From 495420809209dc996580ddd0fdc38e1ff91f7b89 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:36:15 +0000 Subject: [PATCH 4/6] feat: Add role definition support for management group scope and update test configurations --- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 1 + .vscode/settings.json | 22 ++- .../authorization/role-definition/README.md | 167 +++++++++++++++--- .../authorization/role-definition/main.json | 147 +++++++++++++-- .../tests/e2e/mg.default/main.test.bicep | 49 ++--- ...ubscription_owner.alz_role_definition.json | 27 +++ .../tests/e2e/mg.loadJson/main.test.bicep | 53 +++--- 7 files changed, 360 insertions(+), 106 deletions(-) create mode 100644 avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/lib/subscription_owner.alz_role_definition.json diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 8ac2ed9e6b..9acd9fe4f4 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -43,6 +43,7 @@ body: - "avm/ptn/authorization/policy-assignment" - "avm/ptn/authorization/resource-role-assignment" - "avm/ptn/authorization/role-assignment" + - "avm/ptn/authorization/role-definition" # - "avm/ptn/avd-lza/insights" # - "avm/ptn/avd-lza/management-plane" # - "avm/ptn/avd-lza/networking" diff --git a/.vscode/settings.json b/.vscode/settings.json index 05509ca25f..3af57b41c8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -29,5 +29,25 @@ "files.encoding": "utf8bom", "files.insertFinalNewline": true, "editor.detectIndentation": false // VS Code will not detect indentation/tab/space from the file and use settings editor.insertSpaces and editor.tabSize instead - } + }, + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#87fa38", + "activityBar.background": "#87fa38", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#448ffa", + "activityBarBadge.foreground": "#15202b", + "commandCenter.border": "#15202b99", + "sash.hoverBorder": "#87fa38", + "statusBar.background": "#69f906", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#54c705", + "statusBarItem.remoteBackground": "#69f906", + "statusBarItem.remoteForeground": "#15202b", + "titleBar.activeBackground": "#69f906", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveBackground": "#69f90699", + "titleBar.inactiveForeground": "#15202b99" + }, + "peacock.color": "#69f906" } \ No newline at end of file diff --git a/avm/ptn/authorization/role-definition/README.md b/avm/ptn/authorization/role-definition/README.md index 749cc6e4a8..02c3b8e0f9 100644 --- a/avm/ptn/authorization/role-definition/README.md +++ b/avm/ptn/authorization/role-definition/README.md @@ -1,6 +1,6 @@ -# `[Authorization/RoleDefinition]` +# avm/ptn/authorization/role-definition `[Authorization/RoleDefinition]` - +This module deploys a custom role definition to a Management Group. ## Navigation @@ -12,7 +12,9 @@ ## Resource Types -_None_ +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | [2022-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-05-01-preview/roleDefinitions) | ## Usage examples @@ -22,10 +24,13 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/ptn/authorization/role-definition:`. -- [Defaults](#example-1-defaults) -- [Waf-Aligned](#example-2-waf-aligned) +- [Role Definition (Management Group scope) - Required Parameters](#example-1-role-definition-management-group-scope---required-parameters) +- [Role Definition (Management Group scope) - Using loadJsonContent](#example-2-role-definition-management-group-scope---using-loadjsoncontent) + +### Example 1: _Role Definition (Management Group scope) - Required Parameters_ + +This module deploys a Role Definition at a Management Group scope using minimal parameters. -### Example 1: _Defaults_

@@ -36,7 +41,12 @@ module roleDefinition 'br/public:avm/ptn/authorization/role-definition: name: 'roleDefinitionDeployment' params: { // Required parameters - name: 'arddef001' + roleDefinition: { + actions: [ + '*/read' + ] + name: 'rbac-custom-role-reader' + } // Non-required parameters location: '' } @@ -56,8 +66,13 @@ module roleDefinition 'br/public:avm/ptn/authorization/role-definition: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "name": { - "value": "arddef001" + "roleDefinition": { + "value": { + "actions": [ + "*/read" + ], + "name": "rbac-custom-role-reader" + } }, // Non-required parameters "location": { @@ -78,7 +93,12 @@ module roleDefinition 'br/public:avm/ptn/authorization/role-definition: using 'br/public:avm/ptn/authorization/role-definition:' // Required parameters -param name = 'arddef001' +param roleDefinition = { + actions: [ + '*/read' + ] + name: 'rbac-custom-role-reader' +} // Non-required parameters param location = '' ``` @@ -86,7 +106,10 @@ param location = ''

-### Example 2: _Waf-Aligned_ +### Example 2: _Role Definition (Management Group scope) - Using loadJsonContent_ + +This module deploys a Role Definition at a Management Group scope using loadJsonContent to load a custom role definition stored in a JSON file. +

@@ -97,7 +120,15 @@ module roleDefinition 'br/public:avm/ptn/authorization/role-definition: name: 'roleDefinitionDeployment' params: { // Required parameters - name: 'ardwaf001' + roleDefinition: { + actions: '' + dataActions: '' + description: '' + name: '' + notActions: '' + notDataActions: '' + roleName: '' + } // Non-required parameters location: '' } @@ -117,8 +148,16 @@ module roleDefinition 'br/public:avm/ptn/authorization/role-definition: "contentVersion": "1.0.0.0", "parameters": { // Required parameters - "name": { - "value": "ardwaf001" + "roleDefinition": { + "value": { + "actions": "", + "dataActions": "", + "description": "", + "name": "", + "notActions": "", + "notDataActions": "", + "roleName": "" + } }, // Non-required parameters "location": { @@ -139,7 +178,15 @@ module roleDefinition 'br/public:avm/ptn/authorization/role-definition: using 'br/public:avm/ptn/authorization/role-definition:' // Required parameters -param name = 'ardwaf001' +param roleDefinition = { + actions: '' + dataActions: '' + description: '' + name: '' + notActions: '' + notDataActions: '' + roleName: '' +} // Non-required parameters param location = '' ``` @@ -153,22 +200,96 @@ param location = '' | Parameter | Type | Description | | :-- | :-- | :-- | -| [`name`](#parameter-name) | string | Name of the resource to create. | +| [`roleDefinition`](#parameter-roledefinition) | object | Array of custom role definitions to create on the management group. | **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`location`](#parameter-location) | string | Location for all Resources. | +| [`location`](#parameter-location) | string | The location of the telemetry deployment to be created. Default is location of deployment. | + +### Parameter: `roleDefinition` + +Array of custom role definitions to create on the management group. + +- Required: Yes +- Type: object + +**Required parameters** -### Parameter: `name` +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-roledefinitionname) | string | The name of the custom role definition. | -Name of the resource to create. +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`actions`](#parameter-roledefinitionactions) | array | The permission actions of the custom role definition. | +| [`assignableScopes`](#parameter-roledefinitionassignablescopes) | array | The assignable scopes of the custom role definition. If not specified, the management group being targeted in the parameter managementGroupName will be used. | +| [`dataActions`](#parameter-roledefinitiondataactions) | array | The permission data actions of the custom role definition. | +| [`description`](#parameter-roledefinitiondescription) | string | The description of the custom role definition. | +| [`notActions`](#parameter-roledefinitionnotactions) | array | The permission not actions of the custom role definition. | +| [`notDataActions`](#parameter-roledefinitionnotdataactions) | array | The permission not data actions of the custom role definition. | +| [`roleName`](#parameter-roledefinitionrolename) | string | The display name of the custom role definition. If not specified, the name will be used. | + +### Parameter: `roleDefinition.name` + +The name of the custom role definition. - Required: Yes - Type: string +### Parameter: `roleDefinition.actions` + +The permission actions of the custom role definition. + +- Required: No +- Type: array + +### Parameter: `roleDefinition.assignableScopes` + +The assignable scopes of the custom role definition. If not specified, the management group being targeted in the parameter managementGroupName will be used. + +- Required: No +- Type: array + +### Parameter: `roleDefinition.dataActions` + +The permission data actions of the custom role definition. + +- Required: No +- Type: array + +### Parameter: `roleDefinition.description` + +The description of the custom role definition. + +- Required: No +- Type: string + +### Parameter: `roleDefinition.notActions` + +The permission not actions of the custom role definition. + +- Required: No +- Type: array + +### Parameter: `roleDefinition.notDataActions` + +The permission not data actions of the custom role definition. + +- Required: No +- Type: array + +### Parameter: `roleDefinition.roleName` + +The display name of the custom role definition. If not specified, the name will be used. + +- Required: No +- Type: string + ### Parameter: `enableTelemetry` Enable/Disable usage telemetry for module. @@ -179,15 +300,17 @@ Enable/Disable usage telemetry for module. ### Parameter: `location` -Location for all Resources. +The location of the telemetry deployment to be created. Default is location of deployment. - Required: No - Type: string -- Default: `[resourceGroup().location]` +- Default: `[deployment().location]` ## Outputs -_None_ +| Output | Type | +| :-- | :-- | +| `managementGroupCustomRoleDefinitionIds` | object | ## Data Collection diff --git a/avm/ptn/authorization/role-definition/main.json b/avm/ptn/authorization/role-definition/main.json index a62736faa4..5eb54820b4 100644 --- a/avm/ptn/authorization/role-definition/main.json +++ b/avm/ptn/authorization/role-definition/main.json @@ -1,44 +1,126 @@ { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.32.4.45862", - "templateHash": "14578551070113584879" + "templateHash": "6740189645424769245" }, - "name": "", - "description": "", - "owner": "Azure/module-maintainers" + "name": "avm/ptn/authorization/role-definition", + "description": "This module deploys a custom role definition to a Management Group.", + "owner": "@jtracey93" + }, + "definitions": { + "roleDefinitionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the custom role definition." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the custom role definition." + } + }, + "assignableScopes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The assignable scopes of the custom role definition. If not specified, the management group being targeted in the parameter managementGroupName will be used." + } + }, + "actions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The permission actions of the custom role definition." + } + }, + "notActions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The permission not actions of the custom role definition." + } + }, + "dataActions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The permission data actions of the custom role definition." + } + }, + "notDataActions": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The permission not data actions of the custom role definition." + } + }, + "roleName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The display name of the custom role definition. If not specified, the name will be used." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "A type for custom role definition." + } + } }, "parameters": { - "name": { - "type": "string", + "enableTelemetry": { + "type": "bool", + "defaultValue": true, "metadata": { - "description": "Required. Name of the resource to create." + "description": "Optional. Enable/Disable usage telemetry for module." } }, "location": { "type": "string", - "defaultValue": "[resourceGroup().location]", + "defaultValue": "[deployment().location]", "metadata": { - "description": "Optional. Location for all Resources." + "description": "Optional. The location of the telemetry deployment to be created. Default is location of deployment." } }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, + "roleDefinition": { + "$ref": "#/definitions/roleDefinitionType", "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." + "description": "Required. Array of custom role definitions to create on the management group." } } }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", - "name": "[format('46d3xbcp.[[REPLACE WITH TELEMETRY IDENTIFIER]].{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.ptn.authorization-roledefinition.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -53,6 +135,35 @@ } } } + }, + "res_roleDefinition_mg": { + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2022-05-01-preview", + "name": "[if(and(and(contains(parameters('roleDefinition').name, '-'), equals(length(parameters('roleDefinition').name), 36)), equals(length(split(parameters('roleDefinition').name, '-')), 5)), parameters('roleDefinition').name, guid(parameters('roleDefinition').name))]", + "properties": { + "roleName": "[coalesce(tryGet(parameters('roleDefinition'), 'roleName'), parameters('roleDefinition').name)]", + "description": "[tryGet(parameters('roleDefinition'), 'description')]", + "type": "CustomRole", + "assignableScopes": "[coalesce(tryGet(parameters('roleDefinition'), 'assignableScopes'), createArray(managementGroup().id))]", + "permissions": [ + { + "actions": "[coalesce(tryGet(parameters('roleDefinition'), 'actions'), createArray())]", + "notActions": "[coalesce(tryGet(parameters('roleDefinition'), 'notActions'), createArray())]", + "dataActions": "[coalesce(tryGet(parameters('roleDefinition'), 'dataActions'), createArray())]", + "notDataActions": "[coalesce(tryGet(parameters('roleDefinition'), 'notDataActions'), createArray())]" + } + ] + } + } + }, + "outputs": { + "managementGroupCustomRoleDefinitionIds": { + "type": "object", + "value": { + "resourceId": "[extensionResourceId(managementGroup().id, 'Microsoft.Authorization/roleDefinitions', if(and(and(contains(parameters('roleDefinition').name, '-'), equals(length(parameters('roleDefinition').name), 36)), equals(length(split(parameters('roleDefinition').name, '-')), 5)), parameters('roleDefinition').name, guid(parameters('roleDefinition').name)))]", + "roleDefinitionId": "[if(and(and(contains(parameters('roleDefinition').name, '-'), equals(length(parameters('roleDefinition').name), 36)), equals(length(split(parameters('roleDefinition').name, '-')), 5)), parameters('roleDefinition').name, guid(parameters('roleDefinition').name))]", + "displayName": "[reference('res_roleDefinition_mg').roleName]" + } } - ] + } } \ No newline at end of file diff --git a/avm/ptn/authorization/role-definition/tests/e2e/mg.default/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/mg.default/main.test.bicep index 4b1931b306..96f2a029ef 100644 --- a/avm/ptn/authorization/role-definition/tests/e2e/mg.default/main.test.bicep +++ b/avm/ptn/authorization/role-definition/tests/e2e/mg.default/main.test.bicep @@ -1,48 +1,33 @@ -targetScope = 'subscription' +targetScope = 'managementGroup' +metadata name = 'Role Definition (Management Group scope) - Required Parameters' +metadata description = 'This module deploys a Role Definition at a Management Group scope using minimal parameters.' // ========== // // Parameters // // ========== // -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' -param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param resourceLocation string = deployment().location - @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test -param serviceShort string = 'arddef' +param serviceShort string = 'acrdmgdef' -@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +@description('Optional. A token to inject into the name of each resource.') param namePrefix string = '#_namePrefix_#' -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: resourceLocation -} +@description('Optional. The location to deploy resources to.') +param resourceLocation string = deployment().location // ============== // // Test Execution // // ============== // -@batchSize(1) -module testDeployment '../../../main.bicep' = [ - for iteration in ['init', 'idem']: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - // You parameters go here - name: '${namePrefix}${serviceShort}001' - location: resourceLocation +module testDeployment '../../../main.bicep' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' + params: { + roleDefinition: { + name: '${namePrefix}-rbac-custom-role-reader' + actions: [ + '*/read' + ] } + location: resourceLocation } -] +} diff --git a/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/lib/subscription_owner.alz_role_definition.json b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/lib/subscription_owner.alz_role_definition.json new file mode 100644 index 0000000000..b09d16ac6b --- /dev/null +++ b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/lib/subscription_owner.alz_role_definition.json @@ -0,0 +1,27 @@ +{ + "name": "402344ce-48c4-5ac1-9320-16726050f964", + "type": "Microsoft.Authorization/roleDefinitions", + "apiVersion": "2018-01-01-preview", + "properties": { + "roleName": "Subscription-Owner", + "description": "Delegated role for subscription owner generated from subscription Owner role", + "type": "CustomRole", + "permissions": [ + { + "actions": [ + "*" + ], + "notActions": [ + "Microsoft.Authorization/*/write", + "Microsoft.Network/vpnGateways/*", + "Microsoft.Network/expressRouteCircuits/*", + "Microsoft.Network/routeTables/write", + "Microsoft.Network/vpnSites/*" + ], + "dataActions": [], + "notDataActions": [] + } + ], + "assignableScopes": [] + } +} \ No newline at end of file diff --git a/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep index 3e71c58018..5c4f71f2db 100644 --- a/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep +++ b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep @@ -1,48 +1,35 @@ -targetScope = 'subscription' +targetScope = 'managementGroup' +metadata name = 'Role Definition (Management Group scope) - Using loadJsonContent' +metadata description = 'This module deploys a Role Definition at a Management Group scope using loadJsonContent to load a custom role definition stored in a JSON file.' // ========== // // Parameters // // ========== // -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -// e.g., for a module 'network/private-endpoint' you could use 'dep-dev-network.privateendpoints-${serviceShort}-rg' -param resourceGroupName string = 'dep-${namePrefix}---${serviceShort}-rg' +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'acrdmgjson' @description('Optional. The location to deploy resources to.') param resourceLocation string = deployment().location -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -// e.g., for a module 'network/private-endpoint' you could use 'npe' as a prefix and then 'waf' as a suffix for the waf-aligned test -param serviceShort string = 'ardwaf' - -@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: resourceLocation -} - // ============== // // Test Execution // // ============== // -@batchSize(1) -module testDeployment '../../../main.bicep' = [ - for iteration in ['init', 'idem']: { - scope: resourceGroup - name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' - params: { - // You parameters go here - name: '${namePrefix}${serviceShort}001' - location: resourceLocation +param customRoleDefinitionJson object = loadJsonContent('lib/subscription_owner.alz_role_definition.json') + +module testDeployment '../../../main.bicep' = { + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}' + params: { + roleDefinition: { + name: customRoleDefinitionJson.name + roleName: customRoleDefinitionJson.properties.roleName + description: customRoleDefinitionJson.properties.description + actions: customRoleDefinitionJson.properties.permissions[0].actions + notActions: customRoleDefinitionJson.properties.permissions[0].notActions + dataActions: customRoleDefinitionJson.properties.permissions[0].dataActions + notDataActions: customRoleDefinitionJson.properties.permissions[0].notDataActions } + location: resourceLocation } -] +} From 98d73cb9340b5d7f80288362208bdb3301c5cebd Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:46:44 +0000 Subject: [PATCH 5/6] feat: Enhance documentation and metadata for management group custom role definition outputs --- avm/ptn/authorization/role-definition/README.md | 6 +++--- avm/ptn/authorization/role-definition/main.bicep | 1 + avm/ptn/authorization/role-definition/main.json | 5 ++++- .../role-definition/tests/e2e/mg.loadJson/main.test.bicep | 3 +++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/avm/ptn/authorization/role-definition/README.md b/avm/ptn/authorization/role-definition/README.md index 02c3b8e0f9..c31da1e1e3 100644 --- a/avm/ptn/authorization/role-definition/README.md +++ b/avm/ptn/authorization/role-definition/README.md @@ -308,9 +308,9 @@ The location of the telemetry deployment to be created. Default is location of d ## Outputs -| Output | Type | -| :-- | :-- | -| `managementGroupCustomRoleDefinitionIds` | object | +| Output | Type | Description | +| :-- | :-- | :-- | +| `managementGroupCustomRoleDefinitionIds` | object | An object containing the resourceId, roleDefinitionId, and displayName of the custom role definition. | ## Data Collection diff --git a/avm/ptn/authorization/role-definition/main.bicep b/avm/ptn/authorization/role-definition/main.bicep index 6e6c732f3f..9edf391266 100644 --- a/avm/ptn/authorization/role-definition/main.bicep +++ b/avm/ptn/authorization/role-definition/main.bicep @@ -65,6 +65,7 @@ resource res_roleDefinition_mg 'Microsoft.Authorization/roleDefinitions@2022-05- // Outputs // // ============ // +@description('An object containing the resourceId, roleDefinitionId, and displayName of the custom role definition.') output managementGroupCustomRoleDefinitionIds object = { resourceId: res_roleDefinition_mg.id roleDefinitionId: res_roleDefinition_mg.name diff --git a/avm/ptn/authorization/role-definition/main.json b/avm/ptn/authorization/role-definition/main.json index 5eb54820b4..1dee5463f0 100644 --- a/avm/ptn/authorization/role-definition/main.json +++ b/avm/ptn/authorization/role-definition/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.32.4.45862", - "templateHash": "6740189645424769245" + "templateHash": "9655529713252686344" }, "name": "avm/ptn/authorization/role-definition", "description": "This module deploys a custom role definition to a Management Group.", @@ -159,6 +159,9 @@ "outputs": { "managementGroupCustomRoleDefinitionIds": { "type": "object", + "metadata": { + "description": "An object containing the resourceId, roleDefinitionId, and displayName of the custom role definition." + }, "value": { "resourceId": "[extensionResourceId(managementGroup().id, 'Microsoft.Authorization/roleDefinitions', if(and(and(contains(parameters('roleDefinition').name, '-'), equals(length(parameters('roleDefinition').name), 36)), equals(length(split(parameters('roleDefinition').name, '-')), 5)), parameters('roleDefinition').name, guid(parameters('roleDefinition').name)))]", "roleDefinitionId": "[if(and(and(contains(parameters('roleDefinition').name, '-'), equals(length(parameters('roleDefinition').name), 36)), equals(length(split(parameters('roleDefinition').name, '-')), 5)), parameters('roleDefinition').name, guid(parameters('roleDefinition').name))]", diff --git a/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep index 5c4f71f2db..f65749b6d9 100644 --- a/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep +++ b/avm/ptn/authorization/role-definition/tests/e2e/mg.loadJson/main.test.bicep @@ -9,6 +9,9 @@ metadata description = 'This module deploys a Role Definition at a Management Gr @description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') param serviceShort string = 'acrdmgjson' +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + @description('Optional. The location to deploy resources to.') param resourceLocation string = deployment().location From 972e83f813bd8b41e7b2563fd53ffa32b3947a14 Mon Sep 17 00:00:00 2001 From: Jack Tracey <41163455+jtracey93@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:54:09 +0000 Subject: [PATCH 6/6] feat: Add location parameter to role definition resources in Bicep and JSON templates --- avm/ptn/authorization/role-definition/main.bicep | 1 + avm/ptn/authorization/role-definition/main.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/avm/ptn/authorization/role-definition/main.bicep b/avm/ptn/authorization/role-definition/main.bicep index 9edf391266..7327aad691 100644 --- a/avm/ptn/authorization/role-definition/main.bicep +++ b/avm/ptn/authorization/role-definition/main.bicep @@ -20,6 +20,7 @@ param roleDefinition roleDefinitionType #disable-next-line no-deployments-resources resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { name: '46d3xbcp.ptn.authorization-roledefinition.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + location: location properties: { mode: 'Incremental' template: { diff --git a/avm/ptn/authorization/role-definition/main.json b/avm/ptn/authorization/role-definition/main.json index 1dee5463f0..ecc4c9f8a4 100644 --- a/avm/ptn/authorization/role-definition/main.json +++ b/avm/ptn/authorization/role-definition/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.32.4.45862", - "templateHash": "9655529713252686344" + "templateHash": "10522781211627883338" }, "name": "avm/ptn/authorization/role-definition", "description": "This module deploys a custom role definition to a Management Group.", @@ -121,6 +121,7 @@ "type": "Microsoft.Resources/deployments", "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.ptn.authorization-roledefinition.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "location": "[parameters('location')]", "properties": { "mode": "Incremental", "template": {