diff --git a/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml b/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml index de861c4f52..7e045cf889 100644 --- a/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml +++ b/.azuredevops/modulePipelines/ms.authorization.policyassignments.yml @@ -42,10 +42,18 @@ stages: parameters: removeDeployment: '${{ parameters.removeDeployment }}' deploymentBlocks: - - path: $(modulePath)/.parameters/min.parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policyAssignments_sub.bicep - - path: $(modulePath)/.parameters/parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policyAssignments_sub.bicep + - path: $(modulePath)/.parameters/mg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/mg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep - stage: Publishing displayName: Publish module diff --git a/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml b/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml index 4b2f2aaad4..41bfa990da 100644 --- a/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml +++ b/.azuredevops/modulePipelines/ms.authorization.policydefinitions.yml @@ -42,10 +42,14 @@ stages: parameters: removeDeployment: '${{ parameters.removeDeployment }}' deploymentBlocks: - - path: $(modulePath)/.parameters/min.parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policyDefinitions_sub.bicep - - path: $(modulePath)/.parameters/parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policyDefinitions_sub.bicep + - path: $(modulePath)/.parameters/mg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/mg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.parameters.json + templateFilePath: $(modulePath)/deploy.bicep - stage: Publishing displayName: Publish module diff --git a/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml b/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml index 7a879e7a96..f43f19850f 100644 --- a/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml +++ b/.azuredevops/modulePipelines/ms.authorization.policyexemptions.yml @@ -42,10 +42,18 @@ stages: parameters: removeDeployment: '${{ parameters.removeDeployment }}' deploymentBlocks: - - path: $(modulePath)/.parameters/min.parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policyExemptions_sub.bicep - - path: $(modulePath)/.parameters/parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policyExemptions_sub.bicep + - path: $(modulePath)/.parameters/mg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/mg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep - stage: Publishing displayName: Publish module diff --git a/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml b/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml index 9744ad6659..56bade6aef 100644 --- a/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml +++ b/.azuredevops/modulePipelines/ms.authorization.policysetdefinitions.yml @@ -42,10 +42,14 @@ stages: parameters: removeDeployment: '${{ parameters.removeDeployment }}' deploymentBlocks: - - path: $(modulePath)/.parameters/min.parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policySetDefinition_sub.bicep - - path: $(modulePath)/.parameters/parameters.json - templateFilePath: $(modulePath)/.bicep/nested_policySetDefinition_sub.bicep + - path: $(modulePath)/.parameters/mg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/mg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.parameters.json + templateFilePath: $(modulePath)/deploy.bicep - stage: Publishing displayName: Publish module diff --git a/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml b/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml index b5797df0d5..b4ad7d6ad8 100644 --- a/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml +++ b/.azuredevops/modulePipelines/ms.authorization.roleassignments.yml @@ -42,10 +42,18 @@ stages: parameters: removeDeployment: '${{ parameters.removeDeployment }}' deploymentBlocks: - - path: $(modulePath)/.parameters/min.parameters.json - templateFilePath: $(modulePath)/.bicep/nested_rbac_sub.bicep - - path: $(modulePath)/.parameters/parameters.json - templateFilePath: $(modulePath)/.bicep/nested_rbac_sub.bicep + - path: $(modulePath)/.parameters/mg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/mg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep - stage: Publishing displayName: Publish module diff --git a/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml b/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml index 476fbfa93e..044f4f0ad5 100644 --- a/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml +++ b/.azuredevops/modulePipelines/ms.authorization.roledefinitions.yml @@ -42,10 +42,18 @@ stages: parameters: removeDeployment: '${{ parameters.removeDeployment }}' deploymentBlocks: - - path: $(modulePath)/.parameters/min.parameters.json - templateFilePath: $(modulePath)/.bicep/nested_roleDefinitions_sub.bicep - - path: $(modulePath)/.parameters/parameters.json - templateFilePath: $(modulePath)/.bicep/nested_roleDefinitions_sub.bicep + - path: $(modulePath)/.parameters/mg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/mg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/sub.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.min.parameters.json + templateFilePath: $(modulePath)/deploy.bicep + - path: $(modulePath)/.parameters/rg.parameters.json + templateFilePath: $(modulePath)/deploy.bicep - stage: Publishing displayName: Publish module diff --git a/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml b/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml index 373c58ab2c..0d263d687a 100644 --- a/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml +++ b/.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml @@ -216,7 +216,7 @@ jobs: pwsh: true inline: | # Load used functions - . (Join-Path '$(moduleRepoRoot)' '$(pipelineFunctionsPath)' 'resourceValidation' 'Test-TemplateWithParameterFile.ps1') + . (Join-Path '$(moduleRepoRoot)' '$(pipelineFunctionsPath)' 'resourceDeployment' 'Test-TemplateWithParameterFile.ps1') if(-not [String]::IsNullOrEmpty('${{ deploymentBlock.templateFilePath }}')) { $templateFilePath = Join-Path '$(moduleRepoRoot)' '${{ deploymentBlock.templateFilePath }}' diff --git a/.azuredevops/platformPipelines/platform.dependencies.yml b/.azuredevops/platformPipelines/platform.dependencies.yml index d6191cc43f..88bd93488c 100644 --- a/.azuredevops/platformPipelines/platform.dependencies.yml +++ b/.azuredevops/platformPipelines/platform.dependencies.yml @@ -91,7 +91,7 @@ stages: - deploy_rg variables: resourceType: 'Microsoft.Authorization/policyAssignments' - templateFilePath: $(modulesPath)/$(resourceType)/.bicep/nested_policyAssignments_sub.bicep + templateFilePath: $(modulesPath)/$(resourceType)/subscription/deploy.bicep jobs: - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml parameters: @@ -803,7 +803,7 @@ stages: - deploy_msi variables: resourceType: 'Microsoft.Authorization/roleAssignments' - templateFilePath: $(modulesPath)/$(resourceType)/.bicep/nested_rbac_sub.bicep + templateFilePath: $(modulesPath)/$(resourceType)/subscription/deploy.bicep msiPrincipalId: $[ stageDependencies.deploy_msi.job_set_msi_id.outputs['print_msi_prinId.msiPrincipalId'] ] jobs: - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml diff --git a/.github/actions/templates/validateModuleDeployment/action.yml b/.github/actions/templates/validateModuleDeployment/action.yml index 7de3f13a47..8723340ce7 100644 --- a/.github/actions/templates/validateModuleDeployment/action.yml +++ b/.github/actions/templates/validateModuleDeployment/action.yml @@ -138,7 +138,7 @@ runs: Write-Output "::group::Validate [${{ inputs.templateFilePath }}]" # Load used functions - . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'resourceValidation' 'Test-TemplateWithParameterFile.ps1') + . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'resourceDeployment' 'Test-TemplateWithParameterFile.ps1') # ----------- # # INVOKE TEST # diff --git a/.github/workflows/ms.authorization.policyassignments.yml b/.github/workflows/ms.authorization.policyassignments.yml index d35c7f00e3..d3f7ab32f1 100644 --- a/.github/workflows/ms.authorization.policyassignments.yml +++ b/.github/workflows/ms.authorization.policyassignments.yml @@ -81,7 +81,15 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json', 'min.parameters.json'] + parameterFilePaths: + [ + 'mg.parameters.json', + 'mg.min.parameters.json', + 'sub.parameters.json', + 'sub.min.parameters.json', + 'rg.parameters.json', + 'rg.min.parameters.json', + ] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -98,7 +106,7 @@ jobs: - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/.bicep/nested_policyAssignments_sub.bicep' + templateFilePath: '${{ env.modulePath }}/deploy.bicep' parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.resourceGroupName }}' diff --git a/.github/workflows/ms.authorization.policydefinitions.yml b/.github/workflows/ms.authorization.policydefinitions.yml index a82a689df1..bbe8334fe3 100644 --- a/.github/workflows/ms.authorization.policydefinitions.yml +++ b/.github/workflows/ms.authorization.policydefinitions.yml @@ -81,7 +81,13 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json', 'min.parameters.json'] + parameterFilePaths: + [ + 'mg.min.parameters.json', + 'mg.parameters.json', + 'sub.min.parameters.json', + 'sub.parameters.json', + ] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -98,7 +104,7 @@ jobs: - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/.bicep/nested_policyDefinitions_sub.bicep' + templateFilePath: '${{ env.modulePath }}/deploy.bicep' parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.resourceGroupName }}' diff --git a/.github/workflows/ms.authorization.policyexemptions.yml b/.github/workflows/ms.authorization.policyexemptions.yml index 3401aef4d4..f9a30d8819 100644 --- a/.github/workflows/ms.authorization.policyexemptions.yml +++ b/.github/workflows/ms.authorization.policyexemptions.yml @@ -81,7 +81,15 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json', 'min.parameters.json'] + parameterFilePaths: + [ + 'mg.parameters.json', + 'mg.min.parameters.json', + 'sub.parameters.json', + 'sub.min.parameters.json', + 'rg.parameters.json', + 'rg.min.parameters.json', + ] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -98,7 +106,7 @@ jobs: - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/.bicep/nested_policyExemptions_sub.bicep' + templateFilePath: '${{ env.modulePath }}/deploy.bicep' parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.resourceGroupName }}' diff --git a/.github/workflows/ms.authorization.policysetdefinitions.yml b/.github/workflows/ms.authorization.policysetdefinitions.yml index 36601975aa..09264ddb36 100644 --- a/.github/workflows/ms.authorization.policysetdefinitions.yml +++ b/.github/workflows/ms.authorization.policysetdefinitions.yml @@ -81,7 +81,13 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json', 'min.parameters.json'] + parameterFilePaths: + [ + 'mg.min.parameters.json', + 'mg.parameters.json', + 'sub.min.parameters.json', + 'sub.parameters.json', + ] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -98,7 +104,7 @@ jobs: - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/.bicep/nested_policySetDefinition_sub.bicep' + templateFilePath: '${{ env.modulePath }}/deploy.bicep' parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.resourceGroupName }}' diff --git a/.github/workflows/ms.authorization.roleassignments.yml b/.github/workflows/ms.authorization.roleassignments.yml index d3428165a6..6c2576ac42 100644 --- a/.github/workflows/ms.authorization.roleassignments.yml +++ b/.github/workflows/ms.authorization.roleassignments.yml @@ -81,7 +81,15 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json', 'min.parameters.json'] + parameterFilePaths: + [ + 'mg.parameters.json', + 'mg.min.parameters.json', + 'sub.parameters.json', + 'sub.min.parameters.json', + 'rg.parameters.json', + 'rg.min.parameters.json', + ] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -98,7 +106,7 @@ jobs: - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/.bicep/nested_rbac_sub.bicep' + templateFilePath: '${{ env.modulePath }}/deploy.bicep' parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.resourceGroupName }}' diff --git a/.github/workflows/ms.authorization.roledefinitions.yml b/.github/workflows/ms.authorization.roledefinitions.yml index f5d47a3eca..5dd95bcbfd 100644 --- a/.github/workflows/ms.authorization.roledefinitions.yml +++ b/.github/workflows/ms.authorization.roledefinitions.yml @@ -81,7 +81,15 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json', 'min.parameters.json'] + parameterFilePaths: + [ + 'mg.parameters.json', + 'mg.min.parameters.json', + 'sub.parameters.json', + 'sub.min.parameters.json', + 'rg.parameters.json', + 'rg.min.parameters.json', + ] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -98,7 +106,7 @@ jobs: - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/.bicep/nested_roleDefinitions_sub.bicep' + templateFilePath: '${{ env.modulePath }}/deploy.bicep' parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.resourceGroupName }}' diff --git a/.github/workflows/platform.dependencies.yml b/.github/workflows/platform.dependencies.yml index a5152cfd4f..4f499ea2c9 100644 --- a/.github/workflows/platform.dependencies.yml +++ b/.github/workflows/platform.dependencies.yml @@ -137,7 +137,7 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: ['parameters.json'] + parameterFilePaths: ['mg.parameters.json', 'sub.parameters.json'] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -146,7 +146,7 @@ jobs: - name: 'Deploy module' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: 'arm/${{ env.namespace }}/.bicep/nested_policyAssignments_sub.bicep' + templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.defaultResourceGroupName }}' @@ -1135,7 +1135,7 @@ jobs: - name: 'Deploy module' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: 'arm/${{ env.namespace }}/.bicep/nested_rbac_sub.bicep' + templateFilePath: 'arm/${{ env.namespace }}/subscription/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' resourceGroupName: '${{ env.defaultResourceGroupName }}' diff --git a/arm/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json b/arm/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 0000000000..7271e1d839 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/.parameters/mg.min.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-min-mg-polAss" + }, + "policyDefinitionID": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" + } + } +} diff --git a/arm/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json b/arm/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json new file mode 100644 index 0000000000..f140b8c7ed --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/.parameters/mg.parameters.json @@ -0,0 +1,59 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-mg-polAss" + }, + "displayName": { + "value": "[Display Name] Policy Assignment at the management group scope" + }, + "description": { + "value": "[Description] Policy Assignment at the management group scope" + }, + "policyDefinitionId": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/4f9dc7db-30c1-420c-b61a-e1d640128d26" + }, + "parameters": { + "value": { + "tagName": { + "value": "env" + }, + "tagValue": { + "value": "prod" + } + } + }, + "nonComplianceMessage": { + "value": "Violated Policy Assignment - This is a Non Compliance Message" + }, + "enforcementMode": { + "value": "DoNotEnforce" + }, + "metadata": { + "value": { + "category": "Security", + "version": "1.0" + } + }, + "location": { + "value": "australiaeast" + }, + "notScopes": { + "value": [ + "/subscriptions/<>/resourceGroups/validation-rg" + ] + }, + "identity": { + "value": "SystemAssigned" + }, + "roleDefinitionIds": { + "value": [ + "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ] + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json b/arm/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 0000000000..de4e5052aa --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/.parameters/rg.min.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-min-rg-polAss" + }, + "policyDefinitionID": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json b/arm/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json new file mode 100644 index 0000000000..e28b39cfd1 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/.parameters/rg.parameters.json @@ -0,0 +1,62 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-rg-polAss" + }, + "displayName": { + "value": "[Display Name] Policy Assignment at the resource group scope" + }, + "description": { + "value": "[Description] Policy Assignment at the resource group scope" + }, + "policyDefinitionId": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/4f9dc7db-30c1-420c-b61a-e1d640128d26" + }, + "parameters": { + "value": { + "tagName": { + "value": "env" + }, + "tagValue": { + "value": "prod" + } + } + }, + "nonComplianceMessage": { + "value": "Violated Policy Assignment - This is a Non Compliance Message" + }, + "enforcementMode": { + "value": "DoNotEnforce" + }, + "metadata": { + "value": { + "category": "Security", + "version": "1.0" + } + }, + "location": { + "value": "australiaeast" + }, + "notScopes": { + "value": [ + "/subscriptions/<>/resourceGroups/<>/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" + ] + }, + "identity": { + "value": "SystemAssigned" + }, + "roleDefinitionIds": { + "value": [ + "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ] + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyAssignments/.parameters/min.parameters.json b/arm/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json similarity index 88% rename from arm/Microsoft.Authorization/policyAssignments/.parameters/min.parameters.json rename to arm/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json index 71ca5bea76..ebadf2e43b 100644 --- a/arm/Microsoft.Authorization/policyAssignments/.parameters/min.parameters.json +++ b/arm/Microsoft.Authorization/policyAssignments/.parameters/sub.min.parameters.json @@ -3,7 +3,7 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "<>-pass-vm-disk" + "value": "<>-min-sub-polAss" }, "policyDefinitionID": { "value": "/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d" diff --git a/arm/Microsoft.Authorization/policyAssignments/.parameters/parameters.json b/arm/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json similarity index 80% rename from arm/Microsoft.Authorization/policyAssignments/.parameters/parameters.json rename to arm/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json index a38772fd79..cc671f092a 100644 --- a/arm/Microsoft.Authorization/policyAssignments/.parameters/parameters.json +++ b/arm/Microsoft.Authorization/policyAssignments/.parameters/sub.parameters.json @@ -3,13 +3,13 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "<>-pass-tag" + "value": "<>-sub-polAss" }, "displayName": { - "value": "Add a tag to resources" + "value": "[Display Name] Policy Assignment at the subscription scope" }, "description": { - "value": "Adds the specified tag and value when any resource missing this tag is created or updated. Existing resources can be remediated by triggering a remediation task. If the tag exists with a different value it will not be changed. Does not modify tags on resource groups." + "value": "[Description] Policy Assignment at the subscription scope" }, "policyDefinitionId": { "value": "/providers/Microsoft.Authorization/policyDefinitions/4f9dc7db-30c1-420c-b61a-e1d640128d26" diff --git a/arm/Microsoft.Authorization/policyAssignments/deploy.bicep b/arm/Microsoft.Authorization/policyAssignments/deploy.bicep index e2de855d0a..7e5c1b1e83 100644 --- a/arm/Microsoft.Authorization/policyAssignments/deploy.bicep +++ b/arm/Microsoft.Authorization/policyAssignments/deploy.bicep @@ -1,12 +1,15 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy assignment.') -@maxLength(24) +@sys.description('Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope, 64 characters for subscription and resource group scopes.') param name string @sys.description('Optional. This message will be part of response in case of policy violation.') param description string = '' +@sys.description('Optional. The display name of the policy assignment. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + @sys.description('Required. Specifies the ID of the policy definition or policy set definition being assigned.') param policyDefinitionId string @@ -23,9 +26,6 @@ param identity string = 'SystemAssigned' @sys.description('Required. The IDs Of the Azure Role Definition list that is used to assign permissions to the identity. You need to provide either the fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.. See https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles for the list IDs for built-in Roles. They must match on what is on the policy definition') param roleDefinitionIds array = [] -@sys.description('Optional. The display name of the policy assignment.') -param displayName string = '' - @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 = {} @@ -39,8 +39,8 @@ param nonComplianceMessage string = '' ]) param enforcementMode string = 'Default' -@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment') -param managementGroupId string = '' +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment') param subscriptionId string = '' @@ -54,7 +54,7 @@ param notScopes array = [] @sys.description('Optional. Location for all resources.') param location string = deployment().location -module policyAssignment_mg '.bicep/nested_policyAssignments_mg.bicep' = if (!empty(managementGroupId) && empty(subscriptionId) && empty(resourceGroupName)) { +module policyAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-PolicyAssignment-MG-Module' scope: managementGroup(managementGroupId) params: { @@ -74,7 +74,7 @@ module policyAssignment_mg '.bicep/nested_policyAssignments_mg.bicep' = if (!emp } } -module policyAssignment_sub '.bicep/nested_policyAssignments_sub.bicep' = if (empty(managementGroupId) && !empty(subscriptionId) && empty(resourceGroupName)) { +module policyAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-PolicyAssignment-Sub-Module' scope: subscription(subscriptionId) params: { @@ -94,7 +94,7 @@ module policyAssignment_sub '.bicep/nested_policyAssignments_sub.bicep' = if (em } } -module policyAssignment_rg '.bicep/nested_policyAssignments_rg.bicep' = if (empty(managementGroupId) && !empty(resourceGroupName) && !empty(subscriptionId)) { +module policyAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-PolicyAssignment-RG-Module' scope: resourceGroup(subscriptionId, resourceGroupName) params: { @@ -115,10 +115,10 @@ module policyAssignment_rg '.bicep/nested_policyAssignments_rg.bicep' = if (empt } @sys.description('Policy Assignment Name') -output name string = !empty(managementGroupId) ? policyAssignment_mg.outputs.name : (!empty(resourceGroupName) ? policyAssignment_rg.outputs.name : policyAssignment_sub.outputs.name) +output name string = empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_mg.outputs.name : (!empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_sub.outputs.name : policyAssignment_rg.outputs.name) @sys.description('Policy Assignment principal ID') -output principalId string = !empty(managementGroupId) ? policyAssignment_mg.outputs.principalId : (!empty(resourceGroupName) ? policyAssignment_rg.outputs.principalId : policyAssignment_sub.outputs.principalId) +output principalId string = empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_mg.outputs.principalId : (!empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_sub.outputs.principalId : policyAssignment_rg.outputs.principalId) @sys.description('Policy Assignment resource ID') -output resourceId string = !empty(managementGroupId) ? policyAssignment_mg.outputs.resourceId : (!empty(resourceGroupName) ? policyAssignment_rg.outputs.resourceId : policyAssignment_sub.outputs.resourceId) +output resourceId string = empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? policyAssignment_sub.outputs.resourceId : policyAssignment_rg.outputs.resourceId) diff --git a/arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_mg.bicep b/arm/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep similarity index 91% rename from arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_mg.bicep rename to arm/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep index a1346f585c..7cfbb78895 100644 --- a/arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_mg.bicep +++ b/arm/Microsoft.Authorization/policyAssignments/managementGroup/deploy.bicep @@ -1,13 +1,14 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy assignment.') +@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('Optional. This message will be part of response in case of policy violation.') param description string = '' -@sys.description('Optional. The display name of the policy assignment.') +@sys.description('Optional. The display name of the policy assignment. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Required. Specifies the ID of the policy definition or policy set definition being assigned.') @@ -39,8 +40,8 @@ param nonComplianceMessage string = '' ]) param enforcementMode string = 'Default' -@sys.description('Required. The Target Scope for the Policy. The name of the management group for the policy assignment') -param managementGroupId string +@sys.description('Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The policy excluded scopes') param notScopes array = [] diff --git a/arm/Microsoft.Authorization/policyAssignments/managementGroup/readme.md b/arm/Microsoft.Authorization/policyAssignments/managementGroup/readme.md new file mode 100644 index 0000000000..1f527ccc17 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/managementGroup/readme.md @@ -0,0 +1,41 @@ +# Policy Assignment on Management Group level `[Microsoft.Authorization/policyAssignments/managementGroup]` + +With this module you can perform policy assignments on a management group level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. This message will be part of response in case of policy violation. | +| `displayName` | string | | | Optional. The display name of the policy assignment. Maximum length is 128 characters. | +| `enforcementMode` | string | `Default` | `[Default, DoNotEnforce]` | Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `SystemAssigned` | `[SystemAssigned, None]` | Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | Optional. The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope. | +| `nonComplianceMessage` | string | | | Optional. The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | Optional. The policy excluded scopes | +| `parameters` | object | `{object}` | | Optional. Parameters for the policy assignment if needed. | +| `policyDefinitionId` | string | | | Required. Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | `[]` | | Required. The IDs Of the Azure Role Definition list that is used to assign permissions to the identity. You need to provide either the fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'.. See https://docs.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 | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Assignment Name | +| `principalId` | string | Policy Assignment principal ID | +| `resourceId` | string | Policy Assignment resource ID | + +## Template references + +- [Policyassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policyAssignments) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/arm/Microsoft.Authorization/policyAssignments/managementGroup/version.json b/arm/Microsoft.Authorization/policyAssignments/managementGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/managementGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyAssignments/readme.md b/arm/Microsoft.Authorization/policyAssignments/readme.md index ece9977e3b..b7cc490356 100644 --- a/arm/Microsoft.Authorization/policyAssignments/readme.md +++ b/arm/Microsoft.Authorization/policyAssignments/readme.md @@ -1,5 +1,7 @@ # Policy Assignments `[Microsoft.Authorization/policyAssignments]` +With this module you can perform policy assignments across the management group, subscription or resource group scope. + ## Resource types | Resource Type | API Version | @@ -12,13 +14,13 @@ | Parameter Name | Type | Default Value | Possible Values | Description | | :-- | :-- | :-- | :-- | :-- | | `description` | string | | | Optional. This message will be part of response in case of policy violation. | -| `displayName` | string | | | Optional. The display name of the policy assignment. | +| `displayName` | string | | | Optional. The display name of the policy assignment. Maximum length is 128 characters. | | `enforcementMode` | string | `Default` | `[Default, DoNotEnforce]` | Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | | `identity` | string | `SystemAssigned` | `[SystemAssigned, None]` | Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | | `location` | string | `[deployment().location]` | | Optional. Location for all resources. | -| `managementGroupId` | string | | | Optional. The Target Scope for the Policy. The name of the management group for the policy assignment | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The Target Scope for the Policy. The name of the management group for the policy assignment. If not provided, will use the current scope for deployment. | | `metadata` | object | `{object}` | | Optional. The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | -| `name` | string | | | Required. Specifies the name of the policy assignment. | +| `name` | string | | | Required. Specifies the name of the policy assignment. Maximum length is 24 characters for management group scope, 64 characters for subscription and resource group scopes. | | `nonComplianceMessage` | string | | | Optional. The messages that describe why a resource is non-compliant with the policy. | | `notScopes` | array | `[]` | | Optional. The policy excluded scopes | | `parameters` | object | `{object}` | | Optional. Parameters for the policy assignment if needed. | @@ -37,7 +39,7 @@ To deploy resource to a Management Group, provide the `managementGroupId` as an } ``` -> The name of the Management Group in the deployment does not have to match the value of the `managementGroupId` in the input parameters. +> `managementGroupId` is an optional parameter. If not provided, the deployment will use the management group defined in the current deployment scope (i.e. `managementGroup().name`). ### Parameter Usage: `subscriptionId` @@ -64,6 +66,27 @@ To deploy resource to a Resource Group, provide the `subscriptionId` and `resour > The `subscriptionId` is used to enable deployment to a Resource Group Scope, allowing the use of the `resourceGroup()` function from a Management Group Scope. [Additional Details](https://github.com/Azure/bicep/pull/1420). +## Module Usage Guidance + +In general, most of the resources under the `Microsoft.Authorization` namespace allows deploying resources at multiple scopes (management groups, subscriptions, resource groups). The `deploy.bicep` root module is simply an orchestrator module that targets sub-modules for different scopes as seen in the parameter usage section. All sub-modules for this namespace have folders that represent the target scope. For example, if the orchestrator module in the [root](deploy.bicep) needs to target 'subscription' level scopes. It will look at the relative path ['/subscription/deploy.bicep'](./subscription/deploy.bicep) and use this sub-module for the actual deployment, while still passing the same parameters from the root module. + +The above method is useful when you want to use a single point to interact with the module but rely on parameter combinations to achieve the target scope. But what if you want to incorporate this module in other modules with lower scopes? This would force you to deploy the module in scope `managementGroup` regardless and further require you to provide its ID with it. If you do not set the scope to management group, this would be the error that you can expect to face: + +```bicep +Error BCP134: Scope "subscription" is not valid for this module. Permitted scopes: "managementGroup" +``` + +The solution is to have the option of directly targeting the sub-module that achieves the required scope. For example, if you have your own Bicep file wanting to create resources at the subscription level, and also use some of the modules from the `Microsoft.Authorization` namespace, then you can directly use the sub-module ['/subscription/deploy.bicep'](./subscription/deploy.bicep) as a path within your repository, or reference that same published module from the bicep registry. CARML also published the sub-modules so you would be able to reference it like the following: + +**Bicep Registry Reference** +```bicep +module policyassignment 'br:bicepregistry.azurecr.io/bicep/modules/microsoft.authorization.policyassignments.subscription:version' = {} +``` +**Local Path Reference** +```bicep +module policyassignment 'yourpath/arm/Microsoft.Authorization.policyAssignments/subscription/deploy.bicep' = {} +``` + ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Authorization/policyAssignments/resourceGroup/.bicep/nested_cuaId.bicep b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_rg.bicep b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep similarity index 83% rename from arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_rg.bicep rename to arm/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep index 83a284f970..c6e25feff9 100644 --- a/arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_rg.bicep +++ b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/deploy.bicep @@ -1,13 +1,14 @@ targetScope = 'resourceGroup' -@sys.description('Required. Specifies the name of the policy assignment.') -@maxLength(24) +@sys.description('Required. Specifies the name of the policy assignment. Maximum length is 64 characters for resource group scope.') +@maxLength(64) param name string @sys.description('Optional. This message will be part of response in case of policy violation.') param description string = '' -@sys.description('Optional. The display name of the policy assignment.') +@sys.description('Optional. The display name of the policy assignment. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Required. Specifies the ID of the policy definition or policy set definition being assigned.') @@ -49,12 +50,20 @@ var nonComplianceMessage_var = { message: !empty(nonComplianceMessage) ? nonComplianceMessage : null } -@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment') +@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId -@sys.description('Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment') +@sys.description('Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment. If not provided, will use the current scope for deployment.') param resourceGroupName string = resourceGroup().name +@sys.description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + var identity_var = identity == 'SystemAssigned' ? { type: identity } : null @@ -92,3 +101,6 @@ output principalId string = identity == 'SystemAssigned' ? policyAssignment.iden @sys.description('Policy Assignment resource ID') output resourceId string = az.resourceId(subscriptionId, resourceGroupName, 'Microsoft.Authorization/policyAssignments', policyAssignment.name) + +@sys.description('The name of the resource group the policy was assigned to') +output resourceGroupName string = resourceGroup().name diff --git a/arm/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md new file mode 100644 index 0000000000..57000e6618 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/readme.md @@ -0,0 +1,44 @@ +# Policy Assignment on Resource Group level `[Microsoft.Authorization/policyAssignments/resourceGroup]` + +With this module you can perform policy assignments on a resource group level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `description` | string | | | Optional. This message will be part of response in case of policy violation. | +| `displayName` | string | | | Optional. The display name of the policy assignment. Maximum length is 128 characters. | +| `enforcementMode` | string | `Default` | `[Default, DoNotEnforce]` | Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `SystemAssigned` | `[SystemAssigned, None]` | Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all resources. | +| `metadata` | object | `{object}` | | Optional. The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy assignment. Maximum length is 64 characters for resource group scope. | +| `nonComplianceMessage` | string | | | Optional. The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | Optional. The policy excluded scopes | +| `parameters` | object | `{object}` | | Optional. Parameters for the policy assignment if needed. | +| `policyDefinitionId` | string | | | Required. Specifies the ID of the policy definition or policy set definition being assigned. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | Optional. The Target Scope for the Policy. The name of the resource group for the policy assignment. If not provided, will use the current scope for deployment. | +| `roleDefinitionIds` | array | `[]` | | Required. The IDs Of the Azure Role Definition list that is used to assign permissions to the identity. You need to provide either the fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'.. See https://docs.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 | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Assignment Name | +| `principalId` | string | Policy Assignment principal ID | +| `resourceGroupName` | string | The name of the resource group the policy was assigned to | +| `resourceId` | string | Policy Assignment resource ID | + +## Template references + +- [Policyassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policyAssignments) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/arm/Microsoft.Authorization/policyAssignments/resourceGroup/version.json b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/resourceGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_sub.bicep b/arm/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep similarity index 93% rename from arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_sub.bicep rename to arm/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep index 4de3291814..d13fbf2e89 100644 --- a/arm/Microsoft.Authorization/policyAssignments/.bicep/nested_policyAssignments_sub.bicep +++ b/arm/Microsoft.Authorization/policyAssignments/subscription/deploy.bicep @@ -1,13 +1,14 @@ targetScope = 'subscription' -@sys.description('Required. Specifies the name of the policy assignment.') -@maxLength(24) +@sys.description('Required. Specifies the name of the policy assignment. Maximum length is 64 characters for subscription scope.') +@maxLength(64) param name string @sys.description('Optional. This message will be part of response in case of policy violation.') param description string = '' -@sys.description('Optional. The display name of the policy assignment.') +@sys.description('Optional. The display name of the policy assignment. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Required. Specifies the ID of the policy definition or policy set definition being assigned.') @@ -49,7 +50,7 @@ var nonComplianceMessage_var = { message: !empty(nonComplianceMessage) ? nonComplianceMessage : null } -@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment') +@sys.description('Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId var identity_var = identity == 'SystemAssigned' ? { diff --git a/arm/Microsoft.Authorization/policyAssignments/subscription/readme.md b/arm/Microsoft.Authorization/policyAssignments/subscription/readme.md new file mode 100644 index 0000000000..0214edc0c3 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/subscription/readme.md @@ -0,0 +1,41 @@ +# Policy Assignment on Subscription level `[Microsoft.Authorization/policyAssignments/subscription]` + +With this module you can perform policy assignments on a subscription level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyAssignments` | 2021-06-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. This message will be part of response in case of policy violation. | +| `displayName` | string | | | Optional. The display name of the policy assignment. Maximum length is 128 characters. | +| `enforcementMode` | string | `Default` | `[Default, DoNotEnforce]` | Optional. The policy assignment enforcement mode. Possible values are Default and DoNotEnforce. - Default or DoNotEnforce | +| `identity` | string | `SystemAssigned` | `[SystemAssigned, None]` | Optional. The managed identity associated with the policy assignment. Policy assignments must include a resource identity when assigning 'Modify' policy definitions. | +| `location` | string | `[deployment().location]` | | Optional. Location for all resources. | +| `metadata` | object | `{object}` | | Optional. The policy assignment metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy assignment. Maximum length is 64 characters for subscription scope. | +| `nonComplianceMessage` | string | | | Optional. The messages that describe why a resource is non-compliant with the policy. | +| `notScopes` | array | `[]` | | Optional. The policy excluded scopes | +| `parameters` | object | `{object}` | | Optional. Parameters for the policy assignment if needed. | +| `policyDefinitionId` | string | | | Required. Specifies the ID of the policy definition or policy set definition being assigned. | +| `roleDefinitionIds` | array | `[]` | | Required. The IDs Of the Azure Role Definition list that is used to assign permissions to the identity. You need to provide either the fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'.. See https://docs.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 | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The Target Scope for the Policy. The subscription ID of the subscription for the policy assignment. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Assignment Name | +| `principalId` | string | Policy Assignment principal ID | +| `resourceId` | string | Policy Assignment resource ID | + +## Template references + +- [Policyassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policyAssignments) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/arm/Microsoft.Authorization/policyAssignments/subscription/version.json b/arm/Microsoft.Authorization/policyAssignments/subscription/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyAssignments/subscription/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json b/arm/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 0000000000..431a0f6f5e --- /dev/null +++ b/arm/Microsoft.Authorization/policyDefinitions/.parameters/mg.min.parameters.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-mg-min-policyDef" + }, + "policyRule": { + "value": { + "if": { + "allOf": [ + { + "equals": "Microsoft.KeyVault/vaults", + "field": "type" + } + ] + }, + "then": { + "effect": "[parameters('effect')]" + } + } + }, + "parameters": { + "value": { + "effect": { + "allowedValues": [ + "Audit" + ], + "defaultValue": "Audit", + "type": "String" + } + } + } + } +} diff --git a/arm/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json b/arm/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json new file mode 100644 index 0000000000..7196de6154 --- /dev/null +++ b/arm/Microsoft.Authorization/policyDefinitions/.parameters/mg.parameters.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-mg-policyDef" + }, + "displayName": { + "value": "[DisplayName] This policy definition is deployed at the management group scope" + }, + "description": { + "value": "[Description] This policy definition is deployed at the management group scope" + }, + "policyRule": { + "value": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions" + }, + { + "field": "[concat('tags[', parameters('tagName'), ']')]", + "exists": "false" + } + ] + }, + "then": { + "effect": "modify", + "details": { + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f" + ], + "operations": [ + { + "operation": "add", + "field": "[concat('tags[', parameters('tagName'), ']')]", + "value": "[parameters('tagValue')]" + } + ] + } + } + } + }, + "parameters": { + "value": { + "tagName": { + "type": "String", + "metadata": { + "displayName": "Tag Name", + "description": "Name of the tag, such as 'environment'" + } + }, + "tagValue": { + "type": "String", + "metadata": { + "displayName": "Tag Value", + "description": "Value of the tag, such as 'production'" + } + } + } + }, + "metadata": { + "value": { + "category": "Security" + } + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyDefinitions/.parameters/min.parameters.json b/arm/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json similarity index 94% rename from arm/Microsoft.Authorization/policyDefinitions/.parameters/min.parameters.json rename to arm/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json index 2ec0f2a318..f2cd03cfb5 100644 --- a/arm/Microsoft.Authorization/policyDefinitions/.parameters/min.parameters.json +++ b/arm/Microsoft.Authorization/policyDefinitions/.parameters/sub.min.parameters.json @@ -3,7 +3,7 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "<>-deny-keyvault-public-min" + "value": "<>-sub-min-policyDef" }, "policyRule": { "value": { diff --git a/arm/Microsoft.Authorization/policyDefinitions/.parameters/parameters.json b/arm/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json similarity index 90% rename from arm/Microsoft.Authorization/policyDefinitions/.parameters/parameters.json rename to arm/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json index 0758fa8e21..e445127518 100644 --- a/arm/Microsoft.Authorization/policyDefinitions/.parameters/parameters.json +++ b/arm/Microsoft.Authorization/policyDefinitions/.parameters/sub.parameters.json @@ -3,13 +3,13 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "<>-add-tag-to-sub-policy" + "value": "<>-sub-policyDef" }, "displayName": { - "value": "[Test] This policy adds tags to a subscription" + "value": "[DisplayName] This policy definition is deployed at subscription scope" }, "description": { - "value": "This is the description of a policy that adds tags to a subscription" + "value": "[Description] This policy definition is deployed at subscription scope" }, "policyRule": { "value": { diff --git a/arm/Microsoft.Authorization/policyDefinitions/deploy.bicep b/arm/Microsoft.Authorization/policyDefinitions/deploy.bicep index c106eba896..198a9be60f 100644 --- a/arm/Microsoft.Authorization/policyDefinitions/deploy.bicep +++ b/arm/Microsoft.Authorization/policyDefinitions/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy definition.') +@sys.description('Required. Specifies the name of the policy definition. Maximum length is 64 characters for management group scope and subscription scope.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy definition.') +@sys.description('Optional. The display name of the policy definition. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The policy definition description.') @@ -29,8 +30,8 @@ param parameters object = {} @sys.description('Required. The Policy Rule details for the Policy Definition') param policyRule object -@sys.description('Optional. The group ID of the Management Group (Scope). Cannot be used with subscriptionId and does not support tenant level deployment (i.e. \'/\')') -param managementGroupId string = '' +@sys.description('Optional. The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The subscription ID of the subscription (Scope). Cannot be used with managementGroupId') param subscriptionId string = '' @@ -38,7 +39,7 @@ param subscriptionId string = '' @sys.description('Optional. Location for all resources.') param location string = deployment().location -module policyDefinition_mg '.bicep/nested_policyDefinitions_mg.bicep' = if (empty(subscriptionId) && !empty(managementGroupId)) { +module policyDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-PolicyDefinition-MG-Module' scope: managementGroup(managementGroupId) params: { @@ -53,7 +54,7 @@ module policyDefinition_mg '.bicep/nested_policyDefinitions_mg.bicep' = if (empt } } -module policyDefinition_sub '.bicep/nested_policyDefinitions_sub.bicep' = if (empty(managementGroupId) && !empty(subscriptionId)) { +module policyDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-PolicyDefinition-Sub-Module' scope: subscription(subscriptionId) params: { @@ -69,10 +70,10 @@ module policyDefinition_sub '.bicep/nested_policyDefinitions_sub.bicep' = if (em } @sys.description('Policy Definition Name') -output name string = !empty(managementGroupId) ? policyDefinition_mg.outputs.name : policyDefinition_sub.outputs.name +output name string = empty(subscriptionId) ? policyDefinition_mg.outputs.name : policyDefinition_sub.outputs.name @sys.description('Policy Definition resource ID') -output resourceId string = !empty(managementGroupId) ? policyDefinition_mg.outputs.resourceId : policyDefinition_sub.outputs.resourceId +output resourceId string = empty(subscriptionId) ? policyDefinition_mg.outputs.resourceId : policyDefinition_sub.outputs.resourceId @sys.description('Policy Definition Role Definition IDs') -output roleDefinitionIds array = !empty(managementGroupId) ? policyDefinition_mg.outputs.roleDefinitionIds : policyDefinition_sub.outputs.roleDefinitionIds +output roleDefinitionIds array = empty(subscriptionId) ? policyDefinition_mg.outputs.roleDefinitionIds : policyDefinition_sub.outputs.roleDefinitionIds diff --git a/arm/Microsoft.Authorization/policyDefinitions/.bicep/nested_policyDefinitions_mg.bicep b/arm/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep similarity index 87% rename from arm/Microsoft.Authorization/policyDefinitions/.bicep/nested_policyDefinitions_mg.bicep rename to arm/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep index 4e64f8d450..2e0046ff26 100644 --- a/arm/Microsoft.Authorization/policyDefinitions/.bicep/nested_policyDefinitions_mg.bicep +++ b/arm/Microsoft.Authorization/policyDefinitions/managementGroup/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy definition.') +@sys.description('Required. Specifies the name of the policy definition. Maximum length is 64 characters.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy definition.') +@sys.description('Optional. The display name of the policy definition. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The policy definition description.') @@ -29,8 +30,8 @@ param parameters object = {} @sys.description('Required. The Policy Rule details for the Policy Definition') param policyRule object -@sys.description('Required. The group ID of the Management Group') -param managementGroupId string +@sys.description('Optional. The group ID of the Management Group. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name resource policyDefinition 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { name: name diff --git a/arm/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md b/arm/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md new file mode 100644 index 0000000000..ba5d7fe803 --- /dev/null +++ b/arm/Microsoft.Authorization/policyDefinitions/managementGroup/readme.md @@ -0,0 +1,34 @@ +# Policy Definitions on Management Group level `[Microsoft.Authorization/policyDefinitions/managementGroup]` + +With this module you can create policy definitions on a management group level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. The policy definition description. | +| `displayName` | string | | | Optional. The display name of the policy definition. Maximum length is 128 characters. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the Management Group. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `mode` | string | `All` | `[All, Indexed, Microsoft.KeyVault.Data, Microsoft.ContainerService.Data, Microsoft.Kubernetes.Data]` | Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `name` | string | | | Required. Specifies the name of the policy definition. Maximum length is 64 characters. | +| `parameters` | object | `{object}` | | Optional. The policy definition parameters that can be used in policy definition references. | +| `policyRule` | object | | | Required. The Policy Rule details for the Policy Definition | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Definition Name | +| `resourceId` | string | Policy Definition resource ID | +| `roleDefinitionIds` | array | Policy Definition Role Definition IDs | + +## Template references + +- [Policydefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policyDefinitions) diff --git a/arm/Microsoft.Authorization/policyDefinitions/managementGroup/version.json b/arm/Microsoft.Authorization/policyDefinitions/managementGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyDefinitions/managementGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyDefinitions/readme.md b/arm/Microsoft.Authorization/policyDefinitions/readme.md index ad5bf2f763..5190891a52 100644 --- a/arm/Microsoft.Authorization/policyDefinitions/readme.md +++ b/arm/Microsoft.Authorization/policyDefinitions/readme.md @@ -1,5 +1,7 @@ # Policy Definitions `[Microsoft.Authorization/policyDefinitions]` +With this module you can create policy definitions across the management group or subscription scope. + ## Resource types | Resource Type | API Version | @@ -11,12 +13,12 @@ | Parameter Name | Type | Default Value | Possible Values | Description | | :-- | :-- | :-- | :-- | :-- | | `description` | string | | | Optional. The policy definition description. | -| `displayName` | string | | | Optional. The display name of the policy definition. | +| `displayName` | string | | | Optional. The display name of the policy definition. Maximum length is 128 characters. | | `location` | string | `[deployment().location]` | | Optional. Location for all resources. | -| `managementGroupId` | string | | | Optional. The group ID of the Management Group (Scope). Cannot be used with subscriptionId and does not support tenant level deployment (i.e. '/') | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment. | | `metadata` | object | `{object}` | | Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | | `mode` | string | `All` | `[All, Indexed, Microsoft.KeyVault.Data, Microsoft.ContainerService.Data, Microsoft.Kubernetes.Data]` | Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | -| `name` | string | | | Required. Specifies the name of the policy definition. | +| `name` | string | | | Required. Specifies the name of the policy definition. Maximum length is 64 characters for management group scope and subscription scope. | | `parameters` | object | `{object}` | | Optional. The policy definition parameters that can be used in policy definition references. | | `policyRule` | object | | | Required. The Policy Rule details for the Policy Definition | | `subscriptionId` | string | | | Optional. The subscription ID of the subscription (Scope). Cannot be used with managementGroupId | @@ -31,7 +33,7 @@ To deploy resource to a Management Group, provide the `managementGroupId` as an } ``` -> The name of the Management Group in the deployment does not have to match the value of the `managementGroupId` in the input parameters. +> `managementGroupId` is an optional parameter. If not provided, the deployment will use the management group defined in the current deployment scope (i.e. `managementGroup().name`). ### Parameter Usage: `subscriptionId` @@ -43,6 +45,27 @@ To deploy resource to an Azure Subscription, provide the `subscriptionId` as an } ``` +## Module Usage Guidance + +In general, most of the resources under the `Microsoft.Authorization` namespace allows deploying resources at multiple scopes (management groups, subscriptions, resource groups). The `deploy.bicep` root module is simply an orchestrator module that targets sub-modules for different scopes as seen in the parameter usage section. All sub-modules for this namespace have folders that represent the target scope. For example, if the orchestrator module in the [root](deploy.bicep) needs to target 'subscription' level scopes. It will look at the relative path ['/subscription/deploy.bicep'](./subscription/deploy.bicep) and use this sub-module for the actual deployment, while still passing the same parameters from the root module. + +The above method is useful when you want to use a single point to interact with the module but rely on parameter combinations to achieve the target scope. But what if you want to incorporate this module in other modules with lower scopes? This would force you to deploy the module in scope `managementGroup` regardless and further require you to provide its ID with it. If you do not set the scope to management group, this would be the error that you can expect to face: + +```bicep +Error BCP134: Scope "subscription" is not valid for this module. Permitted scopes: "managementGroup" +``` + +The solution is to have the option of directly targeting the sub-module that achieves the required scope. For example, if you have your own Bicep file wanting to create resources at the subscription level, and also use some of the modules from the `Microsoft.Authorization` namespace, then you can directly use the sub-module ['/subscription/deploy.bicep'](./subscription/deploy.bicep) as a path within your repository, or reference that same published module from the bicep registry. CARML also published the sub-modules so you would be able to reference it like the following: + +**Bicep Registry Reference** +```bicep +module policydefinition 'br:bicepregistry.azurecr.io/bicep/modules/microsoft.authorization.policydefinitions.subscription:version' = {} +``` +**Local Path Reference** +```bicep +module policydefinition 'yourpath/arm/Microsoft.Authorization.policyDefinitions/subscription/deploy.bicep' = {} +``` + ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Authorization/policyDefinitions/.bicep/nested_policyDefinitions_sub.bicep b/arm/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep similarity index 95% rename from arm/Microsoft.Authorization/policyDefinitions/.bicep/nested_policyDefinitions_sub.bicep rename to arm/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep index 17475973c2..b99c23225c 100644 --- a/arm/Microsoft.Authorization/policyDefinitions/.bicep/nested_policyDefinitions_sub.bicep +++ b/arm/Microsoft.Authorization/policyDefinitions/subscription/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'subscription' -@sys.description('Required. Specifies the name of the policy definition.') +@sys.description('Required. Specifies the name of the policy definition. Maximum length is 64 characters.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy definition.') +@sys.description('Optional. The display name of the policy definition. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The policy definition description.') diff --git a/arm/Microsoft.Authorization/policyDefinitions/subscription/readme.md b/arm/Microsoft.Authorization/policyDefinitions/subscription/readme.md new file mode 100644 index 0000000000..4f47add459 --- /dev/null +++ b/arm/Microsoft.Authorization/policyDefinitions/subscription/readme.md @@ -0,0 +1,34 @@ +# Policy Definitions on Subscription level `[Microsoft.Authorization/policyDefinitions/subscription]` + +With this module you can create policy definitions on a subscription level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyDefinitions` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. The policy definition description. | +| `displayName` | string | | | Optional. The display name of the policy definition. Maximum length is 128 characters. | +| `metadata` | object | `{object}` | | Optional. The policy Definition metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `mode` | string | `All` | `[All, Indexed, Microsoft.KeyVault.Data, Microsoft.ContainerService.Data, Microsoft.Kubernetes.Data]` | Optional. The policy definition mode. Default is All, Some examples are All, Indexed, Microsoft.KeyVault.Data. | +| `name` | string | | | Required. Specifies the name of the policy definition. Maximum length is 64 characters. | +| `parameters` | object | `{object}` | | Optional. The policy definition parameters that can be used in policy definition references. | +| `policyRule` | object | | | Required. The Policy Rule details for the Policy Definition | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The subscription ID of the subscription | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Definition Name | +| `resourceId` | string | Policy Definition resource ID | +| `roleDefinitionIds` | array | Policy Definition Role Definition IDs | + +## Template references + +- [Policydefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policyDefinitions) diff --git a/arm/Microsoft.Authorization/policyDefinitions/subscription/version.json b/arm/Microsoft.Authorization/policyDefinitions/subscription/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyDefinitions/subscription/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json b/arm/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json new file mode 100644 index 0000000000..f5816fcd6d --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/.parameters/mg.min.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-min-mg-polexem" + }, + "policyAssignmentId": { + "value": "/providers/Microsoft.Management/managementGroups/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-mg-pass-loc-rg" + } + } +} diff --git a/arm/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json b/arm/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json new file mode 100644 index 0000000000..2c76ecb64a --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/.parameters/mg.parameters.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-mg-polexem" + }, + "displayName": { + "value": "[Display Name] policy exempt (management group scope)" + }, + "policyAssignmentId": { + "value": "/providers/Microsoft.Management/managementGroups/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-mg-pass-loc-rg" + }, + "exemptionCategory": { + "value": "Waiver" + }, + "metadata": { + "value": { + "category": "Security" + } + }, + "expiresOn": { + "value": "2025-10-02T03:57:00.000Z" + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json b/arm/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json new file mode 100644 index 0000000000..2573b17fe7 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/.parameters/rg.min.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-min-rg-polexem" + }, + "policyAssignmentId": { + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json b/arm/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json new file mode 100644 index 0000000000..68fda77deb --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/.parameters/rg.parameters.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-rg-polexem" + }, + "displayName": { + "value": "[Display Name] policy exempt (resource group scope)" + }, + "policyAssignmentId": { + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" + }, + "exemptionCategory": { + "value": "Waiver" + }, + "metadata": { + "value": { + "category": "Security" + } + }, + "expiresOn": { + "value": "2025-10-02T03:57:00.000Z" + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policyExemptions/.parameters/min.parameters.json b/arm/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json similarity index 74% rename from arm/Microsoft.Authorization/policyExemptions/.parameters/min.parameters.json rename to arm/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json index 576dba2987..920e7d2add 100644 --- a/arm/Microsoft.Authorization/policyExemptions/.parameters/min.parameters.json +++ b/arm/Microsoft.Authorization/policyExemptions/.parameters/sub.min.parameters.json @@ -3,10 +3,10 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "<>-pexe-loc-rg-min" + "value": "<>-min-sub-polexem" }, "policyAssignmentId": { - "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-pass-loc-rg" + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" }, "subscriptionId": { "value": "<>" diff --git a/arm/Microsoft.Authorization/policyExemptions/.parameters/parameters.json b/arm/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json similarity index 77% rename from arm/Microsoft.Authorization/policyExemptions/.parameters/parameters.json rename to arm/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json index 9e88cce8f3..02b3e9037c 100644 --- a/arm/Microsoft.Authorization/policyExemptions/.parameters/parameters.json +++ b/arm/Microsoft.Authorization/policyExemptions/.parameters/sub.parameters.json @@ -3,13 +3,13 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "<>-pexe-loc-rg" + "value": "<>-sub-polexem" }, "displayName": { - "value": "[Test] policy exempt" + "value": "[Display Name] policy exempt (subscription scope)" }, "policyAssignmentId": { - "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-pass-loc-rg" + "value": "/subscriptions/<>/providers/Microsoft.Authorization/policyAssignments/adp-<>-sb-pass-loc-rg" }, "exemptionCategory": { "value": "Waiver" diff --git a/arm/Microsoft.Authorization/policyExemptions/deploy.bicep b/arm/Microsoft.Authorization/policyExemptions/deploy.bicep index e04247f6fc..5f89ad16f7 100644 --- a/arm/Microsoft.Authorization/policyExemptions/deploy.bicep +++ b/arm/Microsoft.Authorization/policyExemptions/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy exemption.') +@sys.description('Required. Specifies the name of the policy exemption. Maximum length is 64 characters for management group, subscription and resource group scopes.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy exemption.') +@sys.description('Optional. The display name of the policy exemption. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The description of the policy exemption.') @@ -29,8 +30,8 @@ param policyDefinitionReferenceIds array = [] @sys.description('Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z ') param expiresOn string = '' -@sys.description('Optional. The group ID of the management group to be exempted from the policy assignment. Cannot use with subscription ID parameter.') -param managementGroupId string = '' +@sys.description('Optional. The group ID of the management group to be exempted from the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The subscription ID of the subscription to be exempted from the policy assignment. Cannot use with management group ID parameter.') param subscriptionId string = '' @@ -41,7 +42,7 @@ param resourceGroupName string = '' @sys.description('Optional. Location for all resources.') param location string = deployment().location -module policyExemption_mg '.bicep/nested_policyExemptions_mg.bicep' = if (!empty(managementGroupId) && empty(subscriptionId) && empty(resourceGroupName)) { +module policyExemption_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-PolicyExemption-MG-Module' scope: managementGroup(managementGroupId) params: { @@ -57,7 +58,7 @@ module policyExemption_mg '.bicep/nested_policyExemptions_mg.bicep' = if (!empty } } -module policyExemption_sub '.bicep/nested_policyExemptions_sub.bicep' = if (empty(managementGroupId) && !empty(subscriptionId) && empty(resourceGroupName)) { +module policyExemption_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-PolicyExemption-Sub-Module' scope: subscription(subscriptionId) params: { @@ -73,7 +74,7 @@ module policyExemption_sub '.bicep/nested_policyExemptions_sub.bicep' = if (empt } } -module policyExemption_rg '.bicep/nested_policyExemptions_rg.bicep' = if (empty(managementGroupId) && !empty(resourceGroupName) && !empty(subscriptionId)) { +module policyExemption_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-PolicyExemption-RG-Module' scope: resourceGroup(subscriptionId, resourceGroupName) params: { @@ -91,10 +92,10 @@ module policyExemption_rg '.bicep/nested_policyExemptions_rg.bicep' = if (empty( } @sys.description('Policy Exemption Name') -output name string = !empty(managementGroupId) ? policyExemption_mg.outputs.name : (!empty(resourceGroupName) ? policyExemption_rg.outputs.name : policyExemption_sub.outputs.name) +output name string = empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_mg.outputs.name : (!empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_sub.outputs.name : policyExemption_rg.outputs.name) @sys.description('Policy Exemption resource ID') -output resourceId string = !empty(managementGroupId) ? policyExemption_mg.outputs.resourceId : (!empty(resourceGroupName) ? policyExemption_rg.outputs.resourceId : policyExemption_sub.outputs.resourceId) +output resourceId string = empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_sub.outputs.resourceId : policyExemption_rg.outputs.resourceId) @sys.description('Policy Exemption Scope') -output scope string = !empty(managementGroupId) ? policyExemption_mg.outputs.scope : (!empty(resourceGroupName) ? policyExemption_rg.outputs.scope : policyExemption_sub.outputs.scope) +output scope string = empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? policyExemption_sub.outputs.scope : policyExemption_rg.outputs.scope) diff --git a/arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_mg.bicep b/arm/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep similarity index 83% rename from arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_mg.bicep rename to arm/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep index 0452dca7d6..c1f1169e93 100644 --- a/arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_mg.bicep +++ b/arm/Microsoft.Authorization/policyExemptions/managementGroup/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy exemption.') +@sys.description('Required. Specifies the name of the policy exemption. Maximum length is 64 characters for management group scope.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy exemption.') +@sys.description('Optional. The display name of the policy assignment. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The description of the policy exemption.') @@ -29,8 +30,8 @@ param policyDefinitionReferenceIds array = [] @sys.description('Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z ') param expiresOn string = '' -@sys.description('Required. The group ID of the management group to be exempted from the policy assignment.') -param managementGroupId string +@sys.description('Optional. The group ID of the management group to be exempted from the policy assignment. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { name: name diff --git a/arm/Microsoft.Authorization/policyExemptions/managementGroup/readme.md b/arm/Microsoft.Authorization/policyExemptions/managementGroup/readme.md new file mode 100644 index 0000000000..3ac4570161 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/managementGroup/readme.md @@ -0,0 +1,35 @@ +# Policy Exemptions on Management Group level `[Microsoft.Authorization/policyExemptions/managementGroup]` + +With this module you can create policy exemptions on a management group level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. The description of the policy exemption. | +| `displayName` | string | | | Optional. The display name of the policy assignment. Maximum length is 128 characters. | +| `exemptionCategory` | string | `Mitigated` | `[Mitigated, Waiver]` | Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | | | Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the management group to be exempted from the policy assignment. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy exemption. Maximum length is 64 characters for management group scope. | +| `policyAssignmentId` | string | | | Required. The resource ID of the policy assignment that is being exempted. | +| `policyDefinitionReferenceIds` | array | `[]` | | Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Exemption Name | +| `resourceId` | string | Policy Exemption resource ID | +| `scope` | string | Policy Exemption Scope | + +## Template references + +- [Policyexemptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-07-01-preview/policyExemptions) diff --git a/arm/Microsoft.Authorization/policyExemptions/managementGroup/version.json b/arm/Microsoft.Authorization/policyExemptions/managementGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/managementGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyExemptions/readme.md b/arm/Microsoft.Authorization/policyExemptions/readme.md index db8449870b..6936706c51 100644 --- a/arm/Microsoft.Authorization/policyExemptions/readme.md +++ b/arm/Microsoft.Authorization/policyExemptions/readme.md @@ -1,5 +1,7 @@ # Policy Exemptions `[Microsoft.Authorization/policyExemptions]` +With this module you can create policy exemptions across the management group, subscription or resource group scope. + ## Resource types | Resource Type | API Version | @@ -11,13 +13,13 @@ | Parameter Name | Type | Default Value | Possible Values | Description | | :-- | :-- | :-- | :-- | :-- | | `description` | string | | | Optional. The description of the policy exemption. | -| `displayName` | string | | | Optional. The display name of the policy exemption. | +| `displayName` | string | | | Optional. The display name of the policy exemption. Maximum length is 128 characters. | | `exemptionCategory` | string | `Mitigated` | `[Mitigated, Waiver]` | Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | | `expiresOn` | string | | | Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z | | `location` | string | `[deployment().location]` | | Optional. Location for all resources. | -| `managementGroupId` | string | | | Optional. The group ID of the management group to be exempted from the policy assignment. Cannot use with subscription ID parameter. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the management group to be exempted from the policy assignment. If not provided, will use the current scope for deployment. | | `metadata` | object | `{object}` | | Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | -| `name` | string | | | Required. Specifies the name of the policy exemption. | +| `name` | string | | | Required. Specifies the name of the policy exemption. Maximum length is 64 characters for management group, subscription and resource group scopes. | | `policyAssignmentId` | string | | | Required. The resource ID of the policy assignment that is being exempted. | | `policyDefinitionReferenceIds` | array | `[]` | | Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | | `resourceGroupName` | string | | | Optional. The name of the resource group to be exempted from the policy assignment. Must also use the subscription ID parameter. | @@ -33,7 +35,7 @@ To deploy resource to a Management Group, provide the `managementGroupId` as an } ``` -> The name of the Management Group in the deployment does not have to match the value of the `managementGroupId` in the input parameters. +> `managementGroupId` is an optional parameter. If not provided, the deployment will use the management group defined in the current deployment scope (i.e. `managementGroup().name`). ### Parameter Usage: `subscriptionId` @@ -60,6 +62,27 @@ To deploy resource to a Resource Group, provide the `subscriptionId` and `resour > The `subscriptionId` is used to enable deployment to a Resource Group Scope, allowing the use of the `resourceGroup()` function from a Management Group Scope. [Additional Details](https://github.com/Azure/bicep/pull/1420). +## Module Usage Guidance + +In general, most of the resources under the `Microsoft.Authorization` namespace allows deploying resources at multiple scopes (management groups, subscriptions, resource groups). The `deploy.bicep` root module is simply an orchestrator module that targets sub-modules for different scopes as seen in the parameter usage section. All sub-modules for this namespace have folders that represent the target scope. For example, if the orchestrator module in the [root](deploy.bicep) needs to target 'subscription' level scopes. It will look at the relative path ['/subscription/deploy.bicep'](./subscription/deploy.bicep) and use this sub-module for the actual deployment, while still passing the same parameters from the root module. + +The above method is useful when you want to use a single point to interact with the module but rely on parameter combinations to achieve the target scope. But what if you want to incorporate this module in other modules with lower scopes? This would force you to deploy the module in scope `managementGroup` regardless and further require you to provide its ID with it. If you do not set the scope to management group, this would be the error that you can expect to face: + +```bicep +Error BCP134: Scope "subscription" is not valid for this module. Permitted scopes: "managementGroup" +``` + +The solution is to have the option of directly targeting the sub-module that achieves the required scope. For example, if you have your own Bicep file wanting to create resources at the subscription level, and also use some of the modules from the `Microsoft.Authorization` namespace, then you can directly use the sub-module ['/subscription/deploy.bicep'](./subscription/deploy.bicep) as a path within your repository, or reference that same published module from the bicep registry. CARML also published the sub-modules so you would be able to reference it like the following: + +**Bicep Registry Reference** +```bicep +module policyexemption 'br:bicepregistry.azurecr.io/bicep/modules/microsoft.authorization.policyexemptions.subscription:version' = {} +``` +**Local Path Reference** +```bicep +module policyexemption 'yourpath/arm/Microsoft.Authorization.policyExemptions/subscription/deploy.bicep' = {} +``` + ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Authorization/policyExemptions/resourceGroup/.bicep/nested_cuaId.bicep b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_rg.bicep b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep similarity index 76% rename from arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_rg.bicep rename to arm/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep index a5e16a419f..22caa4f38c 100644 --- a/arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_rg.bicep +++ b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'resourceGroup' -@sys.description('Required. Specifies the name of the policy exemption.') +@sys.description('Required. Specifies the name of the policy exemption. Maximum length is 64 characters for resource group scope.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy exemption.') +@sys.description('Optional. The display name of the policy exemption. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The description of the policy exemption.') @@ -29,12 +30,20 @@ param policyDefinitionReferenceIds array = [] @sys.description('Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z ') param expiresOn string = '' -@sys.description('Optional. The subscription ID of the subscription to be exempted from the policy assignment.') +@sys.description('Optional. The subscription ID of the subscription to be exempted from the policy assignment. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId -@sys.description('Optional. The name of the resource group to be exempted from the policy assignment.') +@sys.description('Optional. The name of the resource group to be exempted from the policy assignment. If not provided, will use the current scope for deployment.') param resourceGroupName string = resourceGroup().name +@sys.description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { name: name properties: { @@ -56,3 +65,6 @@ output resourceId string = az.resourceId(subscriptionId, resourceGroupName, 'Mic @sys.description('Policy Exemption Scope') output scope string = resourceGroup().id + +@sys.description('The name of the resource group the policy exemption was applied at') +output resourceGroupName string = resourceGroup().name diff --git a/arm/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md new file mode 100644 index 0000000000..57fedef4ee --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/readme.md @@ -0,0 +1,38 @@ +# Policy Exemptions on Resource Group level `[Microsoft.Authorization/policyExemptions/resourceGroup]` + +With this module you can create policy exemptions on a resource group level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `description` | string | | | Optional. The description of the policy exemption. | +| `displayName` | string | | | Optional. The display name of the policy exemption. Maximum length is 128 characters. | +| `exemptionCategory` | string | `Mitigated` | `[Mitigated, Waiver]` | Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | | | Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z | +| `metadata` | object | `{object}` | | Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy exemption. Maximum length is 64 characters for resource group scope. | +| `policyAssignmentId` | string | | | Required. The resource ID of the policy assignment that is being exempted. | +| `policyDefinitionReferenceIds` | array | `[]` | | Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | Optional. The name of the resource group to be exempted from the policy assignment. If not provided, will use the current scope for deployment. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The subscription ID of the subscription to be exempted from the policy assignment. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Exemption Name | +| `resourceGroupName` | string | The name of the resource group the policy exemption was applied at | +| `resourceId` | string | Policy Exemption resource ID | +| `scope` | string | Policy Exemption Scope | + +## Template references + +- [Policyexemptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-07-01-preview/policyExemptions) diff --git a/arm/Microsoft.Authorization/policyExemptions/resourceGroup/version.json b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/resourceGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_sub.bicep b/arm/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep similarity index 90% rename from arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_sub.bicep rename to arm/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep index 281adcd048..9d8678ebb4 100644 --- a/arm/Microsoft.Authorization/policyExemptions/.bicep/nested_policyExemptions_sub.bicep +++ b/arm/Microsoft.Authorization/policyExemptions/subscription/deploy.bicep @@ -1,10 +1,11 @@ targetScope = 'subscription' -@sys.description('Required. Specifies the name of the policy exemption.') +@sys.description('Required. Specifies the name of the policy exemption. Maximum length is 64 characters for subscription scope.') @maxLength(64) param name string -@sys.description('Optional. The display name of the policy exemption.') +@sys.description('Optional. The display name of the policy exemption. Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' @sys.description('Optional. The description of the policy exemption.') @@ -29,7 +30,7 @@ param policyDefinitionReferenceIds array = [] @sys.description('Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z ') param expiresOn string = '' -@sys.description('Optional. The subscription ID of the subscription to be exempted from the policy assignment.') +@sys.description('Optional. The subscription ID of the subscription to be exempted from the policy assignment. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { diff --git a/arm/Microsoft.Authorization/policyExemptions/subscription/readme.md b/arm/Microsoft.Authorization/policyExemptions/subscription/readme.md new file mode 100644 index 0000000000..111d447838 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/subscription/readme.md @@ -0,0 +1,35 @@ +# Policy Exemptions on Subscription level `[Microsoft.Authorization/policyExemptions/subscription]` + +With this module you can create policy exemptions on a subscription level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policyExemptions` | 2020-07-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. The description of the policy exemption. | +| `displayName` | string | | | Optional. The display name of the policy exemption. Maximum length is 128 characters. | +| `exemptionCategory` | string | `Mitigated` | `[Mitigated, Waiver]` | Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated | +| `expiresOn` | string | | | Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z | +| `metadata` | object | `{object}` | | Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy exemption. Maximum length is 64 characters for subscription scope. | +| `policyAssignmentId` | string | | | Required. The resource ID of the policy assignment that is being exempted. | +| `policyDefinitionReferenceIds` | array | `[]` | | Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The subscription ID of the subscription to be exempted from the policy assignment. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Exemption Name | +| `resourceId` | string | Policy Exemption resource ID | +| `scope` | string | Policy Exemption Scope | + +## Template references + +- [Policyexemptions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-07-01-preview/policyExemptions) diff --git a/arm/Microsoft.Authorization/policyExemptions/subscription/version.json b/arm/Microsoft.Authorization/policyExemptions/subscription/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policyExemptions/subscription/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 0000000000..92f9d4ac2f --- /dev/null +++ b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/mg.min.parameters.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-mg-min-policySet" + }, + "policyDefinitions": { + "value": [ + { + "parameters": { + "listOfAllowedLocations": { + "value": [ + "australiaeast" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c" + } + ] + } + } +} diff --git a/arm/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json new file mode 100644 index 0000000000..029e2d47c8 --- /dev/null +++ b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/mg.parameters.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-mg-policySet" + }, + "displayName": { + "value": "[DisplayName] This policy set definition is deployed at management group scope" + }, + "description": { + "value": "[Description] This policy set definition is deployed at management group scope" + }, + "policyDefinitionGroups": { + "value": [ + { + "name": "Network" + }, + { + "name": "ARM" + } + ] + }, + "policyDefinitions": { + "value": [ + { + "groupNames": [ + "ARM" + ], + "parameters": { + "listOfAllowedLocations": { + "value": [ + "australiaeast" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c", + "policyDefinitionReferenceId": "Allowed locations_1" + }, + { + "groupNames": [ + "ARM" + ], + "parameters": { + "listOfAllowedLocations": { + "value": [ + "australiaeast" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988", + "policyDefinitionReferenceId": "Allowed locations for resource groups_1" + } + ] + }, + "metadata": { + "value": { + "category": "Security", + "version": "1" + } + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/policySetDefinitions/.parameters/min.parameters.json b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json similarity index 93% rename from arm/Microsoft.Authorization/policySetDefinitions/.parameters/min.parameters.json rename to arm/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json index 79e975f267..f6a7e68f64 100644 --- a/arm/Microsoft.Authorization/policySetDefinitions/.parameters/min.parameters.json +++ b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/sub.min.parameters.json @@ -3,7 +3,7 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "test-policySetExample-min" + "value": "<>-sub-min-policySet" }, "policyDefinitions": { "value": [ diff --git a/arm/Microsoft.Authorization/policySetDefinitions/.parameters/parameters.json b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json similarity index 88% rename from arm/Microsoft.Authorization/policySetDefinitions/.parameters/parameters.json rename to arm/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json index 9d2dad9482..16a92428b1 100644 --- a/arm/Microsoft.Authorization/policySetDefinitions/.parameters/parameters.json +++ b/arm/Microsoft.Authorization/policySetDefinitions/.parameters/sub.parameters.json @@ -3,13 +3,13 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "test-policySetExample" - }, - "description": { - "value": "[Test] Set of security policies" + "value": "<>-sub-policySet" }, "displayName": { - "value": "[Test] contoso security Policies" + "value": "[DisplayName] This policy set definition is deployed at subscription scope" + }, + "description": { + "value": "[Description] This policy set definition is deployed at subscription scope" }, "policyDefinitionGroups": { "value": [ diff --git a/arm/Microsoft.Authorization/policySetDefinitions/deploy.bicep b/arm/Microsoft.Authorization/policySetDefinitions/deploy.bicep index e234da767e..7aef6f5258 100644 --- a/arm/Microsoft.Authorization/policySetDefinitions/deploy.bicep +++ b/arm/Microsoft.Authorization/policySetDefinitions/deploy.bicep @@ -1,17 +1,18 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy Set Definition (Initiative).') +@sys.description('Required. Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope and 64 characters for subscription scope.') @maxLength(64) param name string -@sys.description('Optional. The display name of the Set Definition (Initiative)') +@sys.description('Optional. The display name of the Set Definition (Initiative). Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' -@sys.description('Optional. The Description name of the Set Definition (Initiative)') +@sys.description('Optional. The description name of the Set Definition (Initiative)') param description string = '' -@sys.description('Optional. The group ID of the Management Group (Scope). Cannot be used with subscriptionId and does not support tenant level deployment (i.e. \'/\')') -param managementGroupId string = '' +@sys.description('Optional. The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The subscription ID of the subscription (Scope). Cannot be used with managementGroupId') param subscriptionId string = '' @@ -31,7 +32,7 @@ param parameters object = {} @sys.description('Optional. Location for all resources.') param location string = deployment().location -module policySetDefinition_mg '.bicep/nested_policySetDefinition_mg.bicep' = if (empty(subscriptionId) && !empty(managementGroupId)) { +module policySetDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-MG-Module' scope: managementGroup(managementGroupId) params: { @@ -46,7 +47,7 @@ module policySetDefinition_mg '.bicep/nested_policySetDefinition_mg.bicep' = if } } -module policySetDefinition_sub '.bicep/nested_policySetDefinition_sub.bicep' = if (empty(managementGroupId) && !empty(subscriptionId)) { +module policySetDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-PolicySetDefinition-Sub-Module' scope: subscription(subscriptionId) params: { @@ -62,7 +63,7 @@ module policySetDefinition_sub '.bicep/nested_policySetDefinition_sub.bicep' = i } @sys.description('Policy Set Definition Name') -output name string = !empty(managementGroupId) ? policySetDefinition_mg.outputs.name : policySetDefinition_sub.outputs.name +output name string = empty(subscriptionId) ? policySetDefinition_mg.outputs.name : policySetDefinition_sub.outputs.name @sys.description('Policy Set Definition resource ID') -output resourceId string = !empty(managementGroupId) ? policySetDefinition_mg.outputs.resourceId : policySetDefinition_sub.outputs.resourceId +output resourceId string = empty(subscriptionId) ? policySetDefinition_mg.outputs.resourceId : policySetDefinition_sub.outputs.resourceId diff --git a/arm/Microsoft.Authorization/policySetDefinitions/.bicep/nested_policySetDefinition_mg.bicep b/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep similarity index 81% rename from arm/Microsoft.Authorization/policySetDefinitions/.bicep/nested_policySetDefinition_mg.bicep rename to arm/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep index f2d10aed20..192012e44d 100644 --- a/arm/Microsoft.Authorization/policySetDefinitions/.bicep/nested_policySetDefinition_mg.bicep +++ b/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/deploy.bicep @@ -1,17 +1,18 @@ targetScope = 'managementGroup' -@sys.description('Required. Specifies the name of the policy Set Definition (Initiative).') -@maxLength(64) +@sys.description('Required. Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope.') +@maxLength(24) param name string -@sys.description('Optional. The display name of the Set Definition (Initiative)') +@sys.description('Optional. The display name of the Set Definition (Initiative). Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' -@sys.description('Optional. The Description name of the Set Definition (Initiative)') +@sys.description('Optional. The description name of the Set Definition (Initiative)') param description string = '' -@sys.description('Required. The group ID of the Management Group') -param managementGroupId string +@sys.description('Optional. The group ID of the Management Group. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') param metadata object = {} diff --git a/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md b/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md new file mode 100644 index 0000000000..17ed1856b0 --- /dev/null +++ b/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/readme.md @@ -0,0 +1,33 @@ +# Policy Set Definitions on Management Group level `[Microsoft.Authorization/policySetDefinitions/managementGroup]` + +With this module you can create policy set definitions on a management group level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. The description name of the Set Definition (Initiative) | +| `displayName` | string | | | Optional. The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the Management Group. If not provided, will use the current scope for deployment. | +| `metadata` | object | `{object}` | | Optional. The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope. | +| `parameters` | object | `{object}` | | Optional. The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | | Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | +| `policyDefinitions` | array | | | Required. The array of Policy definitions object to include for this policy set. Each object must include the Policy definition ID, and optionally other properties like parameters | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Set Definition Name | +| `resourceId` | string | Policy Set Definition resource ID | + +## Template references + +- [Policysetdefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policySetDefinitions) diff --git a/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json b/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policySetDefinitions/managementGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/policySetDefinitions/readme.md b/arm/Microsoft.Authorization/policySetDefinitions/readme.md index 89f8b7d897..f2f27209c0 100644 --- a/arm/Microsoft.Authorization/policySetDefinitions/readme.md +++ b/arm/Microsoft.Authorization/policySetDefinitions/readme.md @@ -1,5 +1,7 @@ # Policy Set Definitions `[Microsoft.Authorization/policySetDefinitions]` +With this module you can create policy set definitions across the management group or subscription scope. + ## Resource types | Resource Type | API Version | @@ -10,12 +12,12 @@ | Parameter Name | Type | Default Value | Possible Values | Description | | :-- | :-- | :-- | :-- | :-- | -| `description` | string | | | Optional. The Description name of the Set Definition (Initiative) | -| `displayName` | string | | | Optional. The display name of the Set Definition (Initiative) | +| `description` | string | | | Optional. The description name of the Set Definition (Initiative) | +| `displayName` | string | | | Optional. The display name of the Set Definition (Initiative). Maximum length is 128 characters. | | `location` | string | `[deployment().location]` | | Optional. Location for all resources. | -| `managementGroupId` | string | | | Optional. The group ID of the Management Group (Scope). Cannot be used with subscriptionId and does not support tenant level deployment (i.e. '/') | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the Management Group (Scope). If not provided, will use the current scope for deployment. | | `metadata` | object | `{object}` | | Optional. The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | -| `name` | string | | | Required. Specifies the name of the policy Set Definition (Initiative). | +| `name` | string | | | Required. Specifies the name of the policy Set Definition (Initiative). Maximum length is 24 characters for management group scope and 64 characters for subscription scope. | | `parameters` | object | `{object}` | | Optional. The Set Definition (Initiative) parameters that can be used in policy definition references. | | `policyDefinitionGroups` | array | `[]` | | Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | | `policyDefinitions` | array | | | Required. The array of Policy definitions object to include for this policy set. Each object must include the Policy definition ID, and optionally other properties like parameters | @@ -31,7 +33,7 @@ To deploy resource to a Management Group, provide the `managementGroupId` as an } ``` -> The name of the Management Group in the deployment does not have to match the value of the `managementGroupId` in the input parameters. +> `managementGroupId` is an optional parameter. If not provided, the deployment will use the management group defined in the current deployment scope (i.e. `managementGroup().name`). ### Parameter Usage: `subscriptionId` @@ -43,6 +45,27 @@ To deploy resource to an Azure Subscription, provide the `subscriptionId` as an } ``` +## Module Usage Guidance + +In general, most of the resources under the `Microsoft.Authorization` namespace allows deploying resources at multiple scopes (management groups, subscriptions, resource groups). The `deploy.bicep` root module is simply an orchestrator module that targets sub-modules for different scopes as seen in the parameter usage section. All sub-modules for this namespace have folders that represent the target scope. For example, if the orchestrator module in the [root](deploy.bicep) needs to target 'subscription' level scopes. It will look at the relative path ['/subscription/deploy.bicep'](./subscription/deploy.bicep) and use this sub-module for the actual deployment, while still passing the same parameters from the root module. + +The above method is useful when you want to use a single point to interact with the module but rely on parameter combinations to achieve the target scope. But what if you want to incorporate this module in other modules with lower scopes? This would force you to deploy the module in scope `managementGroup` regardless and further require you to provide its ID with it. If you do not set the scope to management group, this would be the error that you can expect to face: + +```bicep +Error BCP134: Scope "subscription" is not valid for this module. Permitted scopes: "managementGroup" +``` + +The solution is to have the option of directly targeting the sub-module that achieves the required scope. For example, if you have your own Bicep file wanting to create resources at the subscription level, and also use some of the modules from the `Microsoft.Authorization` namespace, then you can directly use the sub-module ['/subscription/deploy.bicep'](./subscription/deploy.bicep) as a path within your repository, or reference that same published module from the bicep registry. CARML also published the sub-modules so you would be able to reference it like the following: + +**Bicep Registry Reference** +```bicep +module policysetdefinition 'br:bicepregistry.azurecr.io/bicep/modules/microsoft.authorization.policysetdefinitions.subscription:version' = {} +``` +**Local Path Reference** +```bicep +module policysetdefinition 'yourpath/arm/Microsoft.Authorization.policySetDefinitions/subscription/deploy.bicep' = {} +``` + ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Authorization/policySetDefinitions/.bicep/nested_policySetDefinition_sub.bicep b/arm/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep similarity index 89% rename from arm/Microsoft.Authorization/policySetDefinitions/.bicep/nested_policySetDefinition_sub.bicep rename to arm/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep index 9b0eb89634..236bc90c5c 100644 --- a/arm/Microsoft.Authorization/policySetDefinitions/.bicep/nested_policySetDefinition_sub.bicep +++ b/arm/Microsoft.Authorization/policySetDefinitions/subscription/deploy.bicep @@ -1,13 +1,14 @@ targetScope = 'subscription' -@sys.description('Required. Specifies the name of the policy Set Definition (Initiative).') +@sys.description('Required. Specifies the name of the policy Set Definition (Initiative). Maximum length is 64 characters for subscription scope.') @maxLength(64) param name string -@sys.description('Optional. The display name of the Set Definition (Initiative)') +@sys.description('Optional. The display name of the Set Definition (Initiative). Maximum length is 128 characters.') +@maxLength(128) param displayName string = '' -@sys.description('Optional. The Description name of the Set Definition (Initiative)') +@sys.description('Optional. The description name of the Set Definition (Initiative)') param description string = '' @sys.description('Optional. The subscription ID of the subscription') diff --git a/arm/Microsoft.Authorization/policySetDefinitions/subscription/readme.md b/arm/Microsoft.Authorization/policySetDefinitions/subscription/readme.md new file mode 100644 index 0000000000..11a83a542b --- /dev/null +++ b/arm/Microsoft.Authorization/policySetDefinitions/subscription/readme.md @@ -0,0 +1,33 @@ +# Policy Set Definitions on Subscription level `[Microsoft.Authorization/policySetDefinitions/subscription]` + +With this module you can create policy set definitions on a subscription level. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/policySetDefinitions` | 2021-06-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `description` | string | | | Optional. The description name of the Set Definition (Initiative) | +| `displayName` | string | | | Optional. The display name of the Set Definition (Initiative). Maximum length is 128 characters. | +| `metadata` | object | `{object}` | | Optional. The Set Definition (Initiative) metadata. Metadata is an open ended object and is typically a collection of key-value pairs. | +| `name` | string | | | Required. Specifies the name of the policy Set Definition (Initiative). Maximum length is 64 characters for subscription scope. | +| `parameters` | object | `{object}` | | Optional. The Set Definition (Initiative) parameters that can be used in policy definition references. | +| `policyDefinitionGroups` | array | `[]` | | Optional. The metadata describing groups of policy definition references within the Policy Set Definition (Initiative). | +| `policyDefinitions` | array | | | Required. The array of Policy definitions object to include for this policy set. Each object must include the Policy definition ID, and optionally other properties like parameters | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The subscription ID of the subscription | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Policy Set Definition Name | +| `resourceId` | string | Policy Set Definition resource ID | + +## Template references + +- [Policysetdefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2021-06-01/policySetDefinitions) diff --git a/arm/Microsoft.Authorization/policySetDefinitions/subscription/version.json b/arm/Microsoft.Authorization/policySetDefinitions/subscription/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/policySetDefinitions/subscription/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json b/arm/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json new file mode 100644 index 0000000000..02a409875c --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/.parameters/mg.min.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleDefinitionIdOrName": { + "value": "Storage Queue Data Reader" + }, + "principalId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json b/arm/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json new file mode 100644 index 0000000000..e6362b62aa --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/.parameters/mg.parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleDefinitionIdOrName": { + "value": "Backup Reader" + }, + "description": { + "value": "Role Assignment (management group scope)" + }, + "principalId": { + "value": "<>" + }, + "principalType": { + "value": "ServicePrincipal" + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json b/arm/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json new file mode 100644 index 0000000000..6011dc7e99 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/.parameters/rg.min.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleDefinitionIdOrName": { + "value": "Storage Queue Data Reader" + }, + "principalId": { + "value": "<>" + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json b/arm/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json new file mode 100644 index 0000000000..faf9fc3d90 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/.parameters/rg.parameters.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleDefinitionIdOrName": { + "value": "Backup Reader" + }, + "description": { + "value": "Role Assignment (resource group scope)" + }, + "principalId": { + "value": "<>" + }, + "principalType": { + "value": "ServicePrincipal" + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleAssignments/.parameters/min.parameters.json b/arm/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json similarity index 100% rename from arm/Microsoft.Authorization/roleAssignments/.parameters/min.parameters.json rename to arm/Microsoft.Authorization/roleAssignments/.parameters/sub.min.parameters.json diff --git a/arm/Microsoft.Authorization/roleAssignments/.parameters/parameters.json b/arm/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json similarity index 89% rename from arm/Microsoft.Authorization/roleAssignments/.parameters/parameters.json rename to arm/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json index 938f9a4d6a..346ba64c04 100644 --- a/arm/Microsoft.Authorization/roleAssignments/.parameters/parameters.json +++ b/arm/Microsoft.Authorization/roleAssignments/.parameters/sub.parameters.json @@ -6,7 +6,7 @@ "value": "Backup Reader" }, "description": { - "value": "Custom Role Assignment Sub" + "value": "Role Assignment (subscription scope)" }, "principalId": { "value": "<>" diff --git a/arm/Microsoft.Authorization/roleAssignments/deploy.bicep b/arm/Microsoft.Authorization/roleAssignments/deploy.bicep index baf5ec09f7..01a069ea86 100644 --- a/arm/Microsoft.Authorization/roleAssignments/deploy.bicep +++ b/arm/Microsoft.Authorization/roleAssignments/deploy.bicep @@ -6,14 +6,14 @@ param roleDefinitionIdOrName string @sys.description('Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)') param principalId string -@sys.description('Optional. Name of the Resource Group to assign the RBAC role to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided RBAC role to the subscription.') +@sys.description('Optional. Name of the Resource Group to assign the RBAC role to. If Resource Group name is provided, and Subscription ID is provided, the module deploys at resource group level, therefore assigns the provided RBAC role to the resource group.') param resourceGroupName string = '' @sys.description('Optional. Subscription ID of the subscription to assign the RBAC role to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided RBAC role to the subscription.') param subscriptionId string = '' -@sys.description('Optional. Group ID of the Management Group to assign the RBAC role to. If no Subscription is provided, the module deploys at management group level, therefore assigns the provided RBAC role to the management group.') -param managementGroupId string = '' +@sys.description('Optional. Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. Location for all resources.') param location string = deployment().location @@ -21,7 +21,7 @@ param location string = deployment().location @sys.description('Optional. Description of role assignment') param description string = '' -@sys.description('Optional. Id of the delegated managed identity resource') +@sys.description('Optional. ID of the delegated managed identity resource') param delegatedManagedIdentityResourceId string = '' @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') @@ -44,7 +44,7 @@ param conditionVersion string = '2.0' ]) param principalType string = '' -module roleAssignment_mg '.bicep/nested_rbac_mg.bicep' = if (!empty(managementGroupId) && empty(subscriptionId) && empty(resourceGroupName)) { +module roleAssignment_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-RoleAssignment-MG-Module' scope: managementGroup(managementGroupId) params: { @@ -59,7 +59,7 @@ module roleAssignment_mg '.bicep/nested_rbac_mg.bicep' = if (!empty(managementGr } } -module roleAssignment_sub '.bicep/nested_rbac_sub.bicep' = if (empty(managementGroupId) && !empty(subscriptionId) && empty(resourceGroupName)) { +module roleAssignment_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-RoleAssignment-Sub-Module' scope: subscription(subscriptionId) params: { @@ -74,7 +74,7 @@ module roleAssignment_sub '.bicep/nested_rbac_sub.bicep' = if (empty(managementG } } -module roleAssignment_rg '.bicep/nested_rbac_rg.bicep' = if (empty(managementGroupId) && !empty(resourceGroupName) && !empty(subscriptionId)) { +module roleAssignment_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-RoleAssignment-RG-Module' scope: resourceGroup(subscriptionId, resourceGroupName) params: { @@ -91,10 +91,10 @@ module roleAssignment_rg '.bicep/nested_rbac_rg.bicep' = if (empty(managementGro } @sys.description('The GUID of the Role Assignment') -output name string = !empty(managementGroupId) ? roleAssignment_mg.outputs.name : (!empty(resourceGroupName) ? roleAssignment_rg.outputs.name : roleAssignment_sub.outputs.name) +output name string = empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_mg.outputs.name : (!empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_sub.outputs.name : roleAssignment_rg.outputs.name) @sys.description('The resource ID of the Role Assignment') -output resourceId string = !empty(managementGroupId) ? roleAssignment_mg.outputs.resourceId : (!empty(resourceGroupName) ? roleAssignment_rg.outputs.resourceId : roleAssignment_sub.outputs.resourceId) +output resourceId string = empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_sub.outputs.resourceId : roleAssignment_rg.outputs.resourceId) @sys.description('The scope this Role Assignment applies to') -output scope string = !empty(managementGroupId) ? roleAssignment_mg.outputs.scope : (!empty(resourceGroupName) ? roleAssignment_rg.outputs.scope : roleAssignment_sub.outputs.scope) +output scope string = empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleAssignment_sub.outputs.scope : roleAssignment_rg.outputs.scope) diff --git a/arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_mg.bicep b/arm/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep similarity index 99% rename from arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_mg.bicep rename to arm/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep index a08f85f4c7..1bc2e4ce88 100644 --- a/arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_mg.bicep +++ b/arm/Microsoft.Authorization/roleAssignments/managementGroup/deploy.bicep @@ -6,13 +6,13 @@ param roleDefinitionIdOrName string @sys.description('Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)') param principalId string -@sys.description('Required. Group ID of the Management Group to assign the RBAC role to') -param managementGroupId string +@sys.description('Optional. Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. Description of role assignment') param description string = '' -@sys.description('Optional. Id of the delegated managed identity resource') +@sys.description('Optional. ID of the delegated managed identity resource') param delegatedManagedIdentityResourceId string = '' @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') diff --git a/arm/Microsoft.Authorization/roleAssignments/managementGroup/readme.md b/arm/Microsoft.Authorization/roleAssignments/managementGroup/readme.md new file mode 100644 index 0000000000..10e98eb01b --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/managementGroup/readme.md @@ -0,0 +1,34 @@ +# Role Assignment on Management Group level `[Microsoft.Authorization/roleAssignments/managementGroup]` + +With this module you can perform role assignments on a management group level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | | | Optional. The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `2.0` | `[2.0]` | Optional. Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | | | Optional. ID of the delegated managed identity resource | +| `description` | string | | | Optional. Description of role assignment | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `principalId` | string | | | Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `principalType` | string | | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | Optional. The principal type of the assigned principal ID. | +| `roleDefinitionIdOrName` | string | | | Required. You can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Assignment | +| `resourceId` | string | The scope this Role Assignment applies to | +| `scope` | string | The resource ID of the Role Assignment | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/arm/Microsoft.Authorization/roleAssignments/managementGroup/version.json b/arm/Microsoft.Authorization/roleAssignments/managementGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/managementGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/roleAssignments/readme.md b/arm/Microsoft.Authorization/roleAssignments/readme.md index 6f06757fc1..bbfb50fcc2 100644 --- a/arm/Microsoft.Authorization/roleAssignments/readme.md +++ b/arm/Microsoft.Authorization/roleAssignments/readme.md @@ -1,6 +1,6 @@ # Role Assignments `[Microsoft.Authorization/roleAssignments]` -This module deploys Role Assignments. +This module deploys Role Assignments across the management group, subscription or resource group scope. ## Resource types @@ -14,13 +14,13 @@ This module deploys Role Assignments. | :-- | :-- | :-- | :-- | :-- | | `condition` | string | | | Optional. The conditions on the role assignment. This limits the resources it can be assigned to | | `conditionVersion` | string | `2.0` | `[2.0]` | Optional. Version of the condition. Currently accepted value is "2.0" | -| `delegatedManagedIdentityResourceId` | string | | | Optional. Id of the delegated managed identity resource | +| `delegatedManagedIdentityResourceId` | string | | | Optional. ID of the delegated managed identity resource | | `description` | string | | | Optional. Description of role assignment | | `location` | string | `[deployment().location]` | | Optional. Location for all resources. | -| `managementGroupId` | string | | | Optional. Group ID of the Management Group to assign the RBAC role to. If no Subscription is provided, the module deploys at management group level, therefore assigns the provided RBAC role to the management group. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. Group ID of the Management Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | | `principalId` | string | | | Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | | `principalType` | string | | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | Optional. The principal type of the assigned principal ID. | -| `resourceGroupName` | string | | | Optional. Name of the Resource Group to assign the RBAC role to. If no Resource Group name is provided, and Subscription ID is provided, the module deploys at subscription level, therefore assigns the provided RBAC role to the subscription. | +| `resourceGroupName` | string | | | Optional. Name of the Resource Group to assign the RBAC role to. If Resource Group name is provided, and Subscription ID is provided, the module deploys at resource group level, therefore assigns the provided RBAC role to the resource group. | | `roleDefinitionIdOrName` | string | | | Required. You can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' | | `subscriptionId` | string | | | Optional. Subscription ID of the subscription to assign the RBAC role to. If no Resource Group name is provided, the module deploys at subscription level, therefore assigns the provided RBAC role to the subscription. | @@ -34,7 +34,7 @@ To deploy resource to a Management Group, provide the `managementGroupId` as an } ``` -> The name of the Management Group in the deployment does not have to match the value of the `managementGroupId` in the input parameters. +> `managementGroupId` is an optional parameter. If not provided, the deployment will use the management group defined in the current deployment scope (i.e. `managementGroup().name`). ### Parameter Usage: `subscriptionId` @@ -61,6 +61,27 @@ To deploy resource to a Resource Group, provide the `subscriptionId` and `resour > The `subscriptionId` is used to enable deployment to a Resource Group Scope, allowing the use of the `resourceGroup()` function from a Management Group Scope. [Additional Details](https://github.com/Azure/bicep/pull/1420). +## Module Usage Guidance + +In general, most of the resources under the `Microsoft.Authorization` namespace allows deploying resources at multiple scopes (management groups, subscriptions, resource groups). The `deploy.bicep` root module is simply an orchestrator module that targets sub-modules for different scopes as seen in the parameter usage section. All sub-modules for this namespace have folders that represent the target scope. For example, if the orchestrator module in the [root](deploy.bicep) needs to target 'subscription' level scopes. It will look at the relative path ['/subscription/deploy.bicep'](./subscription/deploy.bicep) and use this sub-module for the actual deployment, while still passing the same parameters from the root module. + +The above method is useful when you want to use a single point to interact with the module but rely on parameter combinations to achieve the target scope. But what if you want to incorporate this module in other modules with lower scopes? This would force you to deploy the module in scope `managementGroup` regardless and further require you to provide its ID with it. If you do not set the scope to management group, this would be the error that you can expect to face: + +```bicep +Error BCP134: Scope "subscription" is not valid for this module. Permitted scopes: "managementGroup" +``` + +The solution is to have the option of directly targeting the sub-module that achieves the required scope. For example, if you have your own Bicep file wanting to create resources at the subscription level, and also use some of the modules from the `Microsoft.Authorization` namespace, then you can directly use the sub-module ['/subscription/deploy.bicep'](./subscription/deploy.bicep) as a path within your repository, or reference that same published module from the bicep registry. CARML also published the sub-modules so you would be able to reference it like the following: + +**Bicep Registry Reference** +```bicep +module roleassignment 'br:bicepregistry.azurecr.io/bicep/modules/microsoft.authorization.roleassignments.subscription:version' = {} +``` +**Local Path Reference** +```bicep +module roleassignment 'yourpath/arm/Microsoft.Authorization.roleAssignments/subscription/deploy.bicep' = {} +``` + ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Authorization/roleAssignments/resourceGroup/.bicep/nested_cuaId.bicep b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_rg.bicep b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep similarity index 98% rename from arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_rg.bicep rename to arm/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep index f851fed2a8..693661c13f 100644 --- a/arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_rg.bicep +++ b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/deploy.bicep @@ -6,16 +6,16 @@ param roleDefinitionIdOrName string @sys.description('Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)') param principalId string -@sys.description('Optional. Name of the Resource Group to assign the RBAC role to.') +@sys.description('Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment.') param resourceGroupName string = resourceGroup().name -@sys.description('Optional. Subscription ID of the subscription to assign the RBAC role to.') +@sys.description('Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId @sys.description('Optional. Description of role assignment') param description string = '' -@sys.description('Optional. Id of the delegated managed identity resource') +@sys.description('Optional. ID of the delegated managed identity resource') param delegatedManagedIdentityResourceId string = '' @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') @@ -38,6 +38,9 @@ param conditionVersion string = '2.0' ]) param principalType string = '' +@sys.description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + var builtInRoleNames_var = { 'AcrPush': '/providers/Microsoft.Authorization/roleDefinitions/8311e382-0749-4cb8-b61a-304f252e45ec' 'API Management Service Contributor': '/providers/Microsoft.Authorization/roleDefinitions/312a565d-c81f-4fd8-895a-4e21e48d571c' @@ -324,6 +327,11 @@ var builtInRoleNames_var = { var roleDefinitionId_var = (contains(builtInRoleNames_var, roleDefinitionIdOrName) ? builtInRoleNames_var[roleDefinitionIdOrName] : roleDefinitionIdOrName) +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = { name: guid(subscriptionId, resourceGroupName, roleDefinitionId_var, principalId) properties: { @@ -345,3 +353,6 @@ output scope string = resourceGroup().id @sys.description('The scope this Role Assignment applies to') output resourceId string = az.resourceId(resourceGroupName, 'Microsoft.Authorization/roleAssignments', roleAssignment.name) + +@sys.description('The name of the resource group the role assignment was applied at') +output resourceGroupName string = resourceGroup().name diff --git a/arm/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md new file mode 100644 index 0000000000..aca00e1a3a --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/readme.md @@ -0,0 +1,37 @@ +# Role Assignment on Resource Group level `[Microsoft.Authorization/roleAssignments/resourceGroup]` + +With this module you can perform role assignments on a resource group level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | | | Optional. The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `2.0` | `[2.0]` | Optional. Version of the condition. Currently accepted value is "2.0" | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `delegatedManagedIdentityResourceId` | string | | | Optional. ID of the delegated managed identity resource | +| `description` | string | | | Optional. Description of role assignment | +| `principalId` | string | | | Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `principalType` | string | | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | Optional. The principal type of the assigned principal ID. | +| `resourceGroupName` | string | `[resourceGroup().name]` | | Optional. Name of the Resource Group to assign the RBAC role to. If not provided, will use the current scope for deployment. | +| `roleDefinitionIdOrName` | string | | | Required. You can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Assignment | +| `resourceGroupName` | string | The name of the resource group the role assignment was applied at | +| `resourceId` | string | The scope this Role Assignment applies to | +| `scope` | string | The resource ID of the Role Assignment | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/arm/Microsoft.Authorization/roleAssignments/resourceGroup/version.json b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/resourceGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_sub.bicep b/arm/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep similarity index 99% rename from arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_sub.bicep rename to arm/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep index 757cb9eb4b..bf5f0fcd9b 100644 --- a/arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_sub.bicep +++ b/arm/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep @@ -6,13 +6,13 @@ param roleDefinitionIdOrName string @sys.description('Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity)') param principalId string -@sys.description('Optional. Subscription ID of the subscription to assign the RBAC role to.') +@sys.description('Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId @sys.description('Optional. Description of role assignment') param description string = '' -@sys.description('Optional. Id of the delegated managed identity resource') +@sys.description('Optional. ID of the delegated managed identity resource') param delegatedManagedIdentityResourceId string = '' @sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to') diff --git a/arm/Microsoft.Authorization/roleAssignments/subscription/readme.md b/arm/Microsoft.Authorization/roleAssignments/subscription/readme.md new file mode 100644 index 0000000000..54917e3356 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/subscription/readme.md @@ -0,0 +1,34 @@ +# Role Assignment on Subscription level `[Microsoft.Authorization/roleAssignments/subscription]` + +With this module you can perform role assignments on a subscription level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `condition` | string | | | Optional. The conditions on the role assignment. This limits the resources it can be assigned to | +| `conditionVersion` | string | `2.0` | `[2.0]` | Optional. Version of the condition. Currently accepted value is "2.0" | +| `delegatedManagedIdentityResourceId` | string | | | Optional. ID of the delegated managed identity resource | +| `description` | string | | | Optional. Description of role assignment | +| `principalId` | string | | | Required. The Principal or Object ID of the Security Principal (User, Group, Service Principal, Managed Identity) | +| `principalType` | string | | `[ServicePrincipal, Group, User, ForeignGroup, Device, ]` | Optional. The principal type of the assigned principal ID. | +| `roleDefinitionIdOrName` | string | | | Required. You can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. Subscription ID of the subscription to assign the RBAC role to. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Assignment | +| `resourceId` | string | The scope this Role Assignment applies to | +| `scope` | string | The resource ID of the Role Assignment | + +## Template references + +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) diff --git a/arm/Microsoft.Authorization/roleAssignments/subscription/version.json b/arm/Microsoft.Authorization/roleAssignments/subscription/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/roleAssignments/subscription/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json b/arm/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json new file mode 100644 index 0000000000..c4a88ba9e8 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/.parameters/mg.min.parameters.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleName": { + "value": "<>-az-testRole-mg-min" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read" + ] + } + } +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json b/arm/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json new file mode 100644 index 0000000000..d49ce1cae3 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/.parameters/mg.parameters.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleName": { + "value": "<>-az-testRole-mg" + }, + "description": { + "value": "Test Custom Role Definition Standard (management group scope)" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/*", + "Microsoft.Network/virtualNetworks/read" + ] + }, + "notActions": { + "value": [ + "Microsoft.Compute/images/write", + "Microsoft.Compute/images/delete", + "Microsoft.Network/virtualNetworks/subnets/join/action" + ] + }, + "dataActions": { + "value": [ + "Microsoft.Storage/storageAccounts/blobServices/*/read" + ] + }, + "notDataActions": { + "value": [ + "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read" + ] + }, + "assignableScopes": { + "value": [ + "/providers/Microsoft.Management/managementGroups/<>" + ] + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json b/arm/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json new file mode 100644 index 0000000000..cf6825cc02 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/.parameters/rg.min.parameters.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleName": { + "value": "<>-az-testRole-rg-min" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/read", + "Microsoft.Compute/galleries/images/read" + ] + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json b/arm/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json new file mode 100644 index 0000000000..c27ff2f862 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/.parameters/rg.parameters.json @@ -0,0 +1,46 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "roleName": { + "value": "<>-az-testRole-rg" + }, + "description": { + "value": "Test Custom Role Definition Standard (resource group scope)" + }, + "actions": { + "value": [ + "Microsoft.Compute/galleries/*", + "Microsoft.Network/virtualNetworks/read" + ] + }, + "notActions": { + "value": [ + "Microsoft.Compute/images/write", + "Microsoft.Compute/images/delete", + "Microsoft.Network/virtualNetworks/subnets/join/action" + ] + }, + "dataActions": { + "value": [ + "Microsoft.Storage/storageAccounts/blobServices/*/read" + ] + }, + "notDataActions": { + "value": [ + "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read" + ] + }, + "assignableScopes": { + "value": [ + "/subscriptions/<>/resourceGroups/<>" + ] + }, + "subscriptionId": { + "value": "<>" + }, + "resourceGroupName": { + "value": "<>" + } + } +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/.parameters/min.parameters.json b/arm/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json similarity index 84% rename from arm/Microsoft.Authorization/roleDefinitions/.parameters/min.parameters.json rename to arm/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json index 84d93c977a..87bbbc20b7 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/.parameters/min.parameters.json +++ b/arm/Microsoft.Authorization/roleDefinitions/.parameters/sub.min.parameters.json @@ -5,9 +5,6 @@ "roleName": { "value": "<>-az-testRole-sub-min" }, - "description": { - "value": "Test Custom Role Definition Min" - }, "actions": { "value": [ "Microsoft.Compute/galleries/read", diff --git a/arm/Microsoft.Authorization/roleDefinitions/.parameters/parameters.json b/arm/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json similarity index 93% rename from arm/Microsoft.Authorization/roleDefinitions/.parameters/parameters.json rename to arm/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json index 758b62edf5..62e03ca98d 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/.parameters/parameters.json +++ b/arm/Microsoft.Authorization/roleDefinitions/.parameters/sub.parameters.json @@ -6,7 +6,7 @@ "value": "<>-az-testRole-sub" }, "description": { - "value": "Test Custom Role Definition Standard" + "value": "Test Custom Role Definition Standard (subscription scope)" }, "actions": { "value": [ diff --git a/arm/Microsoft.Authorization/roleDefinitions/deploy.bicep b/arm/Microsoft.Authorization/roleDefinitions/deploy.bicep index 70da565a26..2fed913ce9 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/deploy.bicep +++ b/arm/Microsoft.Authorization/roleDefinitions/deploy.bicep @@ -18,8 +18,8 @@ param dataActions array = [] @sys.description('Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes') param notDataActions array = [] -@sys.description('Optional. The group ID of the Management Group where the Role Definition and Target Scope will be applied to. Cannot use when Subscription or Resource Groups Parameters are used.') -param managementGroupId string = '' +@sys.description('Optional. The group ID of the Management Group where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. The subscription ID where the Role Definition and Target Scope will be applied to. Use for both Subscription level and Resource Group Level.') param subscriptionId string = '' @@ -33,7 +33,7 @@ param location string = deployment().location @sys.description('Optional. Role definition assignable scopes. If not provided, will use the current scope provided.') param assignableScopes array = [] -module roleDefinition_mg '.bicep/nested_roleDefinitions_mg.bicep' = if (!empty(managementGroupId) && empty(subscriptionId) && empty(resourceGroupName)) { +module roleDefinition_mg 'managementGroup/deploy.bicep' = if (empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-RoleDefinition-MG-Module' scope: managementGroup(managementGroupId) params: { @@ -46,7 +46,7 @@ module roleDefinition_mg '.bicep/nested_roleDefinitions_mg.bicep' = if (!empty(m } } -module roleDefinition_sub '.bicep/nested_roleDefinitions_sub.bicep' = if (empty(managementGroupId) && !empty(subscriptionId) && empty(resourceGroupName)) { +module roleDefinition_sub 'subscription/deploy.bicep' = if (!empty(subscriptionId) && empty(resourceGroupName)) { name: '${uniqueString(deployment().name, location)}-RoleDefinition-Sub-Module' scope: subscription(subscriptionId) params: { @@ -61,7 +61,7 @@ module roleDefinition_sub '.bicep/nested_roleDefinitions_sub.bicep' = if (empty( } } -module roleDefinition_rg '.bicep/nested_roleDefinitions_rg.bicep' = if (empty(managementGroupId) && !empty(resourceGroupName) && !empty(subscriptionId)) { +module roleDefinition_rg 'resourceGroup/deploy.bicep' = if (!empty(resourceGroupName) && !empty(subscriptionId)) { name: '${uniqueString(deployment().name, location)}-RoleDefinition-RG-Module' scope: resourceGroup(subscriptionId, resourceGroupName) params: { @@ -78,10 +78,10 @@ module roleDefinition_rg '.bicep/nested_roleDefinitions_rg.bicep' = if (empty(ma } @sys.description('The GUID of the Role Definition') -output name string = !empty(managementGroupId) ? roleDefinition_mg.outputs.name : (!empty(resourceGroupName) ? roleDefinition_rg.outputs.name : roleDefinition_sub.outputs.name) +output name string = empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_mg.outputs.name : (!empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_sub.outputs.name : roleDefinition_rg.outputs.name) @sys.description('The resource ID of the Role Definition') -output resourceId string = !empty(managementGroupId) ? roleDefinition_mg.outputs.resourceId : (!empty(resourceGroupName) ? roleDefinition_rg.outputs.resourceId : roleDefinition_sub.outputs.resourceId) +output resourceId string = empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_mg.outputs.resourceId : (!empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_sub.outputs.resourceId : roleDefinition_rg.outputs.resourceId) @sys.description('The scope this Role Definition applies to') -output roleDefinitionScope string = !empty(managementGroupId) ? roleDefinition_mg.outputs.scope : (!empty(resourceGroupName) ? roleDefinition_rg.outputs.scope : roleDefinition_sub.outputs.scope) +output roleDefinitionScope string = empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_mg.outputs.scope : (!empty(subscriptionId) && empty(resourceGroupName) ? roleDefinition_sub.outputs.scope : roleDefinition_rg.outputs.scope) diff --git a/arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_mg.bicep b/arm/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep similarity index 86% rename from arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_mg.bicep rename to arm/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep index 107e10adee..b915817aa6 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_mg.bicep +++ b/arm/Microsoft.Authorization/roleDefinitions/managementGroup/deploy.bicep @@ -12,8 +12,8 @@ param actions array = [] @sys.description('Optional. List of denied actions.') param notActions array = [] -@sys.description('Required. The group ID of the Management Group where the Role Definition and Target Scope will be applied to.') -param managementGroupId string +@sys.description('Optional. The group ID of the Management Group where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment.') +param managementGroupId string = managementGroup().name @sys.description('Optional. Role definition assignable scopes. If not provided, will use the current scope provided.') param assignableScopes array = [] diff --git a/arm/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md b/arm/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md new file mode 100644 index 0000000000..50dc65f01f --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/managementGroup/readme.md @@ -0,0 +1,32 @@ +# Role Definitions on Management Group level `[Microsoft.Authorization/roleDefinitions/managementGroup]` + +With this module you can create role definitions on a management group level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Optional. List of allowed actions. | +| `assignableScopes` | array | `[]` | | Optional. Role definition assignable scopes. If not provided, will use the current scope provided. | +| `description` | string | | | Optional. Description of the custom RBAC role to be created. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the Management Group where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment. | +| `notActions` | array | `[]` | | Optional. List of denied actions. | +| `roleName` | string | | | Required. Name of the custom RBAC role to be created. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Definition | +| `resourceId` | string | The resource ID of the Role Definition | +| `scope` | string | The scope this Role Definition applies to | + +## Template references + +- [Roledefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2018-01-01-preview/roleDefinitions) diff --git a/arm/Microsoft.Authorization/roleDefinitions/managementGroup/version.json b/arm/Microsoft.Authorization/roleDefinitions/managementGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/managementGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/readme.md b/arm/Microsoft.Authorization/roleDefinitions/readme.md index b801e79aa4..5df05a8322 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/readme.md +++ b/arm/Microsoft.Authorization/roleDefinitions/readme.md @@ -1,6 +1,6 @@ # Role Definitions `[Microsoft.Authorization/roleDefinitions]` -This module deploys custom RBAC Role Definitions. +This module deploys custom RBAC Role Definitions across the management group, subscription or resource group scope. ## Resource types @@ -17,7 +17,7 @@ This module deploys custom RBAC Role Definitions. | `dataActions` | array | `[]` | | Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | | `description` | string | | | Optional. Description of the custom RBAC role to be created. | | `location` | string | `[deployment().location]` | | Optional. Location for all resources. | -| `managementGroupId` | string | | | Optional. The group ID of the Management Group where the Role Definition and Target Scope will be applied to. Cannot use when Subscription or Resource Groups Parameters are used. | +| `managementGroupId` | string | `[managementGroup().name]` | | Optional. The group ID of the Management Group where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment. | | `notActions` | array | `[]` | | Optional. List of denied actions. | | `notDataActions` | array | `[]` | | Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | | `resourceGroupName` | string | | | Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to. | @@ -34,7 +34,7 @@ To deploy resource to a Management Group, provide the `managementGroupId` as an } ``` -> The name of the Management Group in the deployment does not have to match the value of the `managementGroupId` in the input parameters. +> `managementGroupId` is an optional parameter. If not provided, the deployment will use the management group defined in the current deployment scope (i.e. `managementGroup().name`). ### Parameter Usage: `subscriptionId` @@ -61,6 +61,27 @@ To deploy resource to a Resource Group, provide the `subscriptionId` and `resour > The `subscriptionId` is used to enable deployment to a Resource Group Scope, allowing the use of the `resourceGroup()` function from a Management Group Scope. [Additional Details](https://github.com/Azure/bicep/pull/1420). +## Module Usage Guidance + +In general, most of the resources under the `Microsoft.Authorization` namespace allows deploying resources at multiple scopes (management groups, subscriptions, resource groups). The `deploy.bicep` root module is simply an orchestrator module that targets sub-modules for different scopes as seen in the parameter usage section. All sub-modules for this namespace have folders that represent the target scope. For example, if the orchestrator module in the [root](deploy.bicep) needs to target 'subscription' level scopes. It will look at the relative path ['/subscription/deploy.bicep'](./subscription/deploy.bicep) and use this sub-module for the actual deployment, while still passing the same parameters from the root module. + +The above method is useful when you want to use a single point to interact with the module but rely on parameter combinations to achieve the target scope. But what if you want to incorporate this module in other modules with lower scopes? This would force you to deploy the module in scope `managementGroup` regardless and further require you to provide its ID with it. If you do not set the scope to management group, this would be the error that you can expect to face: + +```bicep +Error BCP134: Scope "subscription" is not valid for this module. Permitted scopes: "managementGroup" +``` + +The solution is to have the option of directly targeting the sub-module that achieves the required scope. For example, if you have your own Bicep file wanting to create resources at the subscription level, and also use some of the modules from the `Microsoft.Authorization` namespace, then you can directly use the sub-module ['/subscription/deploy.bicep'](./subscription/deploy.bicep) as a path within your repository, or reference that same published module from the bicep registry. CARML also published the sub-modules so you would be able to reference it like the following: + +**Bicep Registry Reference** +```bicep +module roledefinition 'br:bicepregistry.azurecr.io/bicep/modules/microsoft.authorization.roledefinitions.subscription:version' = {} +``` +**Local Path Reference** +```bicep +module roledefinition 'yourpath/arm/Microsoft.Authorization.roleDefinitions/subscription/deploy.bicep' = {} +``` + ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/.bicep/nested_cuaId.bicep b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/.bicep/nested_cuaId.bicep new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_rg.bicep b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep similarity index 76% rename from arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_rg.bicep rename to arm/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep index 853507ee64..d55962d78e 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_rg.bicep +++ b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/deploy.bicep @@ -18,15 +18,23 @@ param dataActions array = [] @sys.description('Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes') param notDataActions array = [] -@sys.description('Optional. The subscription ID where the Role Definition and Target Scope will be applied to.') +@sys.description('Optional. The subscription ID where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId -@sys.description('Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to.') +@sys.description('Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment.') param resourceGroupName string = resourceGroup().name @sys.description('Optional. Role definition assignable scopes. If not provided, will use the current scope provided.') param assignableScopes array = [] +@sys.description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered.') +param cuaId string = '' + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2018-01-01-preview' = { name: guid(roleName, subscriptionId, resourceGroupName) properties: { @@ -53,3 +61,6 @@ output scope string = resourceGroup().id @sys.description('The resource ID of the Role Definition') output resourceId string = roleDefinition.id + +@sys.description('The name of the resource group the role definition was created at') +output resourceGroupName string = resourceGroup().name diff --git a/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md new file mode 100644 index 0000000000..f42b3bab26 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/readme.md @@ -0,0 +1,37 @@ +# Role Definitions on Resource Group level `[Microsoft.Authorization/roleDefinitions/resourceGroup]` + +With this module you can create role definitions on a resource group level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Optional. List of allowed actions. | +| `assignableScopes` | array | `[]` | | Optional. Role definition assignable scopes. If not provided, will use the current scope provided. | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered. | +| `dataActions` | array | `[]` | | Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | | | Optional. Description of the custom RBAC role to be created. | +| `notActions` | array | `[]` | | Optional. List of denied actions. | +| `notDataActions` | array | `[]` | | Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `resourceGroupName` | string | `[resourceGroup().name]` | | Optional. The name of the Resource Group where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment. | +| `roleName` | string | | | Required. Name of the custom RBAC role to be created. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The subscription ID where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Definition | +| `resourceGroupName` | string | The name of the resource group the role definition was created at | +| `resourceId` | string | The resource ID of the Role Definition | +| `scope` | string | The scope this Role Definition applies to | + +## Template references + +- [Roledefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2018-01-01-preview/roleDefinitions) diff --git a/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/resourceGroup/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_sub.bicep b/arm/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep similarity index 94% rename from arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_sub.bicep rename to arm/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep index 7141c3330f..abc70bc7f8 100644 --- a/arm/Microsoft.Authorization/roleDefinitions/.bicep/nested_roleDefinitions_sub.bicep +++ b/arm/Microsoft.Authorization/roleDefinitions/subscription/deploy.bicep @@ -18,7 +18,7 @@ param dataActions array = [] @sys.description('Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes') param notDataActions array = [] -@sys.description('Optional. The subscription ID where the Role Definition and Target Scope will be applied to.') +@sys.description('Optional. The subscription ID where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment.') param subscriptionId string = subscription().subscriptionId @sys.description('Optional. Role definition assignable scopes. If not provided, will use the current scope provided.') diff --git a/arm/Microsoft.Authorization/roleDefinitions/subscription/readme.md b/arm/Microsoft.Authorization/roleDefinitions/subscription/readme.md new file mode 100644 index 0000000000..950830c0cd --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/subscription/readme.md @@ -0,0 +1,34 @@ +# Role Definitions on Subscription level `[Microsoft.Authorization/roleDefinitions/subscription]` + +With this module you can create role definitions on a subscription level + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/roleDefinitions` | 2018-01-01-preview | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `actions` | array | `[]` | | Optional. List of allowed actions. | +| `assignableScopes` | array | `[]` | | Optional. Role definition assignable scopes. If not provided, will use the current scope provided. | +| `dataActions` | array | `[]` | | Optional. List of allowed data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `description` | string | | | Optional. Description of the custom RBAC role to be created. | +| `notActions` | array | `[]` | | Optional. List of denied actions. | +| `notDataActions` | array | `[]` | | Optional. List of denied data actions. This is not supported if the assignableScopes contains Management Group Scopes | +| `roleName` | string | | | Required. Name of the custom RBAC role to be created. | +| `subscriptionId` | string | `[subscription().subscriptionId]` | | Optional. The subscription ID where the Role Definition and Target Scope will be applied to. If not provided, will use the current scope for deployment. | + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The GUID of the Role Definition | +| `resourceId` | string | The resource ID of the Role Definition | +| `scope` | string | The scope this Role Definition applies to | + +## Template references + +- [Roledefinitions](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2018-01-01-preview/roleDefinitions) diff --git a/arm/Microsoft.Authorization/roleDefinitions/subscription/version.json b/arm/Microsoft.Authorization/roleDefinitions/subscription/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.Authorization/roleDefinitions/subscription/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +} diff --git a/arm/Microsoft.Network/virtualHubs/hubRouteTables/readme.md b/arm/Microsoft.Network/virtualHubs/hubRouteTables/readme.md index 0305c25995..3898449310 100644 --- a/arm/Microsoft.Network/virtualHubs/hubRouteTables/readme.md +++ b/arm/Microsoft.Network/virtualHubs/hubRouteTables/readme.md @@ -2,7 +2,6 @@ This module deploys virtual hub route tables. - ## Resource Types | Resource Type | API Version | diff --git a/arm/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md b/arm/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md index d4bedcaad6..e4502785b6 100644 --- a/arm/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md +++ b/arm/Microsoft.RecoveryServices/vaults/backupStorageConfig/readme.md @@ -17,7 +17,6 @@ This module deploys the Backup Storage Configuration for the Recovery Service Va | `recoveryVaultName` | string | | | Required. Name of the Azure Recovery Service Vault | | `storageModelType` | string | `GeoRedundant` | `[GeoRedundant, LocallyRedundant, ReadAccessGeoZoneRedundant, ZoneRedundant]` | Optional. Change Vault Storage Type (Works if vault has not registered any backup instance) | - ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Storage/storageAccounts/blobServices/readme.md b/arm/Microsoft.Storage/storageAccounts/blobServices/readme.md index 73bf955e50..fabfe84131 100644 --- a/arm/Microsoft.Storage/storageAccounts/blobServices/readme.md +++ b/arm/Microsoft.Storage/storageAccounts/blobServices/readme.md @@ -31,7 +31,6 @@ This module can be used to deploy a blob service into a storage account. | `name` | string | `default` | | Optional. The name of the blob service | | `storageAccountName` | string | | | Required. Name of the Storage Account. | - ## Outputs | Output Name | Type | Description | diff --git a/arm/Microsoft.Storage/storageAccounts/queueServices/readme.md b/arm/Microsoft.Storage/storageAccounts/queueServices/readme.md index c22e0b3c80..7b87611be7 100644 --- a/arm/Microsoft.Storage/storageAccounts/queueServices/readme.md +++ b/arm/Microsoft.Storage/storageAccounts/queueServices/readme.md @@ -27,7 +27,6 @@ This module can be used to deploy a file share service into a storage account. | `queues` | _[queues](queues/readme.md)_ array | `[]` | | Optional. Queues to create. | | `storageAccountName` | string | | | Required. Name of the Storage Account. | - ## Outputs | Output Name | Type | Description | diff --git a/constructs/Microsoft.Authorization/roleAssignments-multiRolesMultiPrincipals/.bicep/nested_rbac.bicep b/constructs/Microsoft.Authorization/roleAssignments-multiRolesMultiPrincipals/.bicep/nested_rbac.bicep index e4faecb330..4411343e9e 100644 --- a/constructs/Microsoft.Authorization/roleAssignments-multiRolesMultiPrincipals/.bicep/nested_rbac.bicep +++ b/constructs/Microsoft.Authorization/roleAssignments-multiRolesMultiPrincipals/.bicep/nested_rbac.bicep @@ -302,7 +302,7 @@ module roleAssignments_mg '../../../../arm/Microsoft.Authorization/roleAssignmen } }] -module roleAssignments_sub '../../../../arm/Microsoft.Authorization/roleAssignments/.bicep/nested_rbac_sub.bicep' = [for principalId in principalIds: if (empty(managementGroupId) && !empty(subscriptionId) && empty(resourceGroupName)) { +module roleAssignments_sub '../../../../arm/Microsoft.Authorization/roleAssignments/subscription/deploy.bicep' = [for principalId in principalIds: if (empty(managementGroupId) && !empty(subscriptionId) && empty(resourceGroupName)) { name: 'roleAssignments_sub-${guid(deployment().name, location, principalId)}' scope: subscription(subscriptionId) params: { diff --git a/docs/wiki/TestingDesign.md b/docs/wiki/TestingDesign.md index 8639bc806a..79e1b60ebb 100644 --- a/docs/wiki/TestingDesign.md +++ b/docs/wiki/TestingDesign.md @@ -85,7 +85,7 @@ If all other tests passed, the deployment tests are the ultimate module validati Most of the resources are deleted by default after their deployment, to keep costs down and to be able to retest resource modules from scratch in the next run. However, the removal step can be skipped in case further investigation on the deployed resource is needed. For further details, please refer to the (./PipelinesUsage) section. -This happens using the `.github/actions/templates/validateModuleDeploy/scripts/Test-TemplateWithParameterFile.ps1` script. +This happens using the `utilities/pipelines/resourceDeployment/Test-TemplateWithParameterFile.ps1` script. > **Note**
Currently the list of the parameter file used to test the module is hardcoded in the module specific workflow, as the **parameterFilePaths** in the _job_deploy_module_ and _job_tests_module_deploy_validate_ jobs. diff --git a/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/mg.parameters.json b/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/mg.parameters.json new file mode 100644 index 0000000000..2f885520e7 --- /dev/null +++ b/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/mg.parameters.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "adp-<>-mg-pass-loc-rg" + }, + "displayName": { + "value": "[Depedency] Audit resource location matches resource group location (management group scope)" + }, + "policyDefinitionID": { + "value": "/providers/Microsoft.Authorization/policyDefinitions/0a914e76-4921-4c19-b460-a2d36003525a" + }, + "managementGroupId": { + "value": "<>" + } + } +} diff --git a/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/parameters.json b/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/sub.parameters.json similarity index 73% rename from utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/parameters.json rename to utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/sub.parameters.json index 5d6b6faadb..10b7caa757 100644 --- a/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/parameters.json +++ b/utilities/pipelines/dependencies/Microsoft.Authorization/policyAssignments/parameters/sub.parameters.json @@ -3,10 +3,10 @@ "contentVersion": "1.0.0.0", "parameters": { "name": { - "value": "adp-<>-pass-loc-rg" + "value": "adp-<>-sb-pass-loc-rg" }, "displayName": { - "value": "Audit resource location matches resource group location" + "value": "[Depedency] Audit resource location matches resource group location (subscription scope)" }, "policyDefinitionID": { "value": "/providers/Microsoft.Authorization/policyDefinitions/0a914e76-4921-4c19-b460-a2d36003525a" diff --git a/utilities/pipelines/resourceValidation/Test-TemplateWithParameterFile.ps1 b/utilities/pipelines/resourceDeployment/Test-TemplateWithParameterFile.ps1 similarity index 91% rename from utilities/pipelines/resourceValidation/Test-TemplateWithParameterFile.ps1 rename to utilities/pipelines/resourceDeployment/Test-TemplateWithParameterFile.ps1 index dd7eee6f35..6624f6ef8a 100644 --- a/utilities/pipelines/resourceValidation/Test-TemplateWithParameterFile.ps1 +++ b/utilities/pipelines/resourceDeployment/Test-TemplateWithParameterFile.ps1 @@ -27,6 +27,9 @@ Optional. ID of the subscription to deploy into. Mandatory if deploying into a s .PARAMETER managementGroupId Optional. Name of the management group to deploy into. Mandatory if deploying into a management group (management group level) +.PARAMETER additionalParameters +Optional. Additional parameters you can provide with the deployment. E.g. @{ resourceGroupName = 'myResourceGroup' } + .EXAMPLE Test-TemplateWithParameterFile templateFilePath 'ARM/KeyVault/deploy.json' -parameterFilePath 'ARM/KeyVault/.parameters/parameters.json' -location 'WestEurope' -resourceGroupName 'aLegendaryRg' @@ -57,7 +60,10 @@ function Test-TemplateWithParameterFile { [string] $subscriptionId, [Parameter(Mandatory = $false)] - [string] $managementGroupId + [string] $managementGroupId, + + [Parameter(Mandatory = $false)] + [Hashtable] $additionalParameters ) begin { @@ -77,6 +83,11 @@ function Test-TemplateWithParameterFile { } $ValidationErrors = $null + # Additional parameter object provided yes/no + if ($additionalParameters) { + $DeploymentInputs += $additionalParameters + } + $deploymentScope = Get-ScopeOfTemplateFile -TemplateFilePath $templateFilePath ####################### @@ -98,7 +109,7 @@ function Test-TemplateWithParameterFile { if ($subscriptionId) { $Context = Get-AzContext -ListAvailable | Where-Object Subscription -Match $subscriptionId if ($Context) { - $Context | Set-AzContext + $null = $Context | Set-AzContext } } if ($PSCmdlet.ShouldProcess('Subscription level deployment', 'Test')) { diff --git a/utilities/tools/Test-ModuleLocally.ps1 b/utilities/tools/Test-ModuleLocally.ps1 index 1cbe8f9e72..39a60c2be8 100644 --- a/utilities/tools/Test-ModuleLocally.ps1 +++ b/utilities/tools/Test-ModuleLocally.ps1 @@ -123,7 +123,7 @@ function Test-ModuleLocally { . (Join-Path $PSScriptRoot '../pipelines/tokensReplacement/Convert-TokensInFile.ps1') # Load Modules Validation / Deployment Scripts . (Join-Path $PSScriptRoot '../pipelines/resourceDeployment/New-ModuleDeployment.ps1') - . (Join-Path $PSScriptRoot '../pipelines/resourceValidation/Test-TemplateWithParameterFile.ps1') + . (Join-Path $PSScriptRoot '../pipelines/resourceDeployment/Test-TemplateWithParameterFile.ps1') } process {